history_backend.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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" 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/favicon/favicon_changed_details.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_history_backend.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/typed_url_syncable_service.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_favicon_usage.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_service.h" 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/error_delegate_util.h" 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/android/android_provider_backend.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The HistoryBackend consists of a number of components: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase (stores past 3 months of history) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSegmentDatabase (stores groups of URLs for the most visited view). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArchivedDatabase (stores history older than 3 months) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (this does not store visit segments as they expire after 3 mos.) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpireHistoryBackend (manages moving things from HistoryDatabase to 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the ArchivedDatabase and deleting) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we keep segment data for in days. Currently 3 months. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This value needs to be greater or equal to 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependency between MostVisitedModel and the history backend. 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kSegmentDataRetention = 90; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we'll wait to do a commit, so that things are batched together. 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kCommitIntervalSeconds = 10; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time before we re-fetch the favicon. 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kFaviconRefetchDays = 7; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of items we'll allow in the redirect list before 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleting some. 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMaxRedirectCount = 32; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of days old a history entry can be before it is considered "old" 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and is archived. 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kArchiveDaysThreshold = 90; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of top sites to track when recording top page visit stats. 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const size_t kPageVisitStatsMaxTopSites = 50; 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts from PageUsageData to MostVisitedURL. |redirects| is a 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of redirects for this URL. Empty list means no redirects. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RedirectList& redirects) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL mv; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.url = page_data.GetURL(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.title = page_data.GetTitle(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects.empty()) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirects must contain at least the target url. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects = redirects; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last url must be the target url. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mv; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This task is run on a timer so that commits happen at regular intervals 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they are batched together. The important thing about this class is that 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it supports canceling of the task so the reference to the backend will be 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freed. The problem is that when history is shutting down, there is likely 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be one of these commits still pending and holding a reference. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backend can call Cancel to have this task release the reference. The 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task will still run (if we ever get to processing the event before 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown), but it will not do anything. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this is a refcounted object and is not a task in itself. It should 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be assigned to a RunnableMethod. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): bug 1165182: This should be replaced with a 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WeakPtrFactory which will handle everything automatically (like we do 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ExpireHistoryBackend). 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommitLaterTask : public base::RefCounted<CommitLaterTask> { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CommitLaterTask(HistoryBackend* history_backend) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : history_backend_(history_backend) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The backend will call this function if it is being destroyed so that we 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release our reference. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_ = NULL; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCommit() { 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (history_backend_.get()) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_->Commit(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<CommitLaterTask>; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CommitLaterTask() {} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryBackend> history_backend_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HistoryBackend -------------------------------------------------------------- 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistoryBackend::HistoryBackend(const base::FilePath& history_dir, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_dir_(history_dir), 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_(false), 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expirer_(this, bookmark_service), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_(kMaxRedirectCount), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_(NULL), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_(false), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_(bookmark_service) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryBackend::~HistoryBackend() { 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First close the databases before optionally running the "destroy" task. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify an interested party (typically a unit test) that we're done. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(backend_destroy_message_loop_); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_->PostTask(FROM_HERE, backend_destroy_task_); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetAndroidCacheFileName()); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Init(const std::string& languages, bool force_fail) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!force_fail) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitImpl(languages); 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->DBLoaded(); 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_.reset(new TypedUrlSyncableService(this)); 206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memory_pressure_listener_.reset(new base::MemoryPressureListener( 207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this)))); 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PopulateMostVisitedURLMap(); 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& task) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Setting more than one destroy task, overriding"; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_ = message_loop; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_task_ = task; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Closing() { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any scheduled commit will have a reference to us, we must make it 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release that reference before we can be destroyed. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release our reference to the delegate, this reference will be keeping the 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history service alive. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_.reset(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyRenderProcessHostDestruction(const void* host) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.NotifyRenderProcessHostDestruction(host); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetThumbnailFileName() const { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kThumbnailsFilename); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetFaviconsFileName() const { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kFaviconsFilename); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetArchivedFileName() const { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kArchivedHistoryFilename); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetAndroidCacheFileName() const { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kAndroidCacheFilename); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::GetLastSegmentID(VisitID from_visit) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set is used to detect referrer loops. Should not happen, but can 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the database is corrupt. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = from_visit; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (visit_id) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForVisit(visit_id, &row)) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row.segment_id) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row.segment_id; // Found a visit in this change with a segment. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the referrer of this visit, if any. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_id = row.referring_visit; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(visit_id) != visit_set.end()) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in referer chain, giving up"; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(visit_id); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::UpdateSegments( 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time ts) { 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only consider main frames. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!content::PageTransitionIsMainFrame(transition_type)) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SegmentID segment_id = 0; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition_type); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are we at the beginning of a new segment? 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that navigating to an existing entry (with back/forward) reuses the 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same transition type. We are not adding it as a new segment in that case 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because if this was the target of a redirect, we might end up with 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 entries for the same final URL. Ex: User types google.net, gets 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirected to google.com. A segment is created for google.net. On 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // google.com users navigates through a link, then press back. That last 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation is for the entry google.com transition typed. We end up adding 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a segment for that one as well. So we end up with google.net and google.com 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // in the segment table, showing as 2 entries in the NTP. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note also that we should still be updating the visit count for that segment 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which we are not doing now. It should be addressed when 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/96860 is fixed. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((t == content::PAGE_TRANSITION_TYPED || 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t == content::PAGE_TRANSITION_AUTO_BOOKMARK) && 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (transition_type & content::PAGE_TRANSITION_FORWARD_BACK) == 0) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If so, create or get the segment. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string segment_name = db_->ComputeSegmentName(url); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->GetSegmentNamed(segment_name))) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->CreateSegment(url_id, segment_name))) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if we update an existing segment, we update the url used to 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // represent that segment in order to minimize stale most visited 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // images. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateSegmentRepresentationURL(segment_id, url_id); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: it is possible there is no segment ID set for this visit chain. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can happen if the initial navigation wasn't AUTO_BOOKMARK or 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TYPED. (For example GENERATED). In this case this visit doesn't count 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // toward any segment. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = GetLastSegmentID(from_visit))) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the segment in the visit. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->SetSegmentID(visit_id, segment_id)) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, increase the counter for that segment / day. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->IncreaseSegmentVisitCount(segment_id, ts, 1)) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return segment_id; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateWithPageEndTime(const void* host, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 page_id, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_ts) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = tracker_.GetLastVisit(host, page_id, url); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(visit_id, end_ts); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateVisitDuration(VisitID visit_id, const Time end_ts) { 360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the starting visit_time for visit_id. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForVisit(visit_id, &visit_row)) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should never have a negative duration time even when time is skewed. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.visit_duration = end_ts > visit_row.visit_time ? 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_ts - visit_row.visit_time : TimeDelta::FromMicroseconds(0); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { 374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<URLID, VisitID> last_ids(0, tracker_.GetLastVisit( 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.id_scope, request.page_id, request.referrer)); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit_id = last_ids.second; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a redirect chain is given, we expect the last item in that chain to be 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the final URL. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.redirects.empty() || 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects.back() == request.url); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is adding older history, we need to make sure our times 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are correct. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.time < first_recorded_time_) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = request.time; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition request_transition = request.transition; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition stripped_transition = 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(request_transition); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_generated = 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition == content::PAGE_TRANSITION_KEYWORD_GENERATED); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is navigating to a not-previously-typed intranet hostname, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the transition to TYPED so that the omnibox will learn that this is 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a known host. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_redirects = request.redirects.size() > 1; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionIsMainFrame(request_transition) && 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition != content::PAGE_TRANSITION_TYPED) && 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url(has_redirects ? 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects[0] : request.url); 408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (origin_url.SchemeIs(url::kHttpScheme) || 409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) origin_url.SchemeIs(url::kHttpsScheme) || 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) origin_url.SchemeIs(url::kFtpScheme)) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(origin_url.host()); 412a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t registry_length = 413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::GetRegistryLength( 414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) host, 415a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 416a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 417a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (registry_length == 0 && !db_->IsTypedHost(host)) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition = content::PAGE_TRANSITION_TYPED; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition = 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition | 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionGetQualifier(request_transition)); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_redirects) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The single entry is both a chain start and end. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = content::PageTransitionFromInt( 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition | 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect case (one element means just the page itself). 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(request.url, request.time, 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second, t, request.visit_source); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. KEYWORD_GENERATED visits should not 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result in changing most visited, so we don't update segments (most 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visited db). 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_keyword_generated) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(request.url, from_visit_id, last_ids.second, t, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the referrer's duration. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect case. Add the redirect chain. 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition redirect_info = 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects = request.redirects; 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (redirects[0].SchemeIs(content::kAboutScheme)) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the redirect source + referrer is "about" we skip it. This 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happens when a page opens a new frame/window to about:blank and then 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // script sets the URL to somewhere else (used to hide the referrer). It 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be nice to keep all these redirects properly but we don't ever 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see the initial about:blank load, so we don't know where the 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subsequent client redirect came from. 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, we just don't bother hooking up the source of the 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects, so we remove it. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (request_transition & content::PAGE_TRANSITION_CLIENT_REDIRECT) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_CLIENT_REDIRECT; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first entry in the redirect chain initiated a client redirect. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't add this to the database since the referrer is already 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there, so we skip over it but change the transition type of the first 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transition to client redirect. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The referrer is invalid when restoring a session that features an 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // https tab that redirects to a different host or to http. In this 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we don't need to reconnect the new redirect with the existing 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chain. 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.referrer.is_valid()) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.referrer == redirects[0]); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the navigation entry for this visit has replaced that for the 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first visit, remove the CHAIN_END marker from the first visit. This 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can be called a lot, for example, the page cycler, and most of the 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time we won't have changed anything. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.did_replace_entry && 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForVisit(last_ids.second, &visit_row) && 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & content::PAGE_TRANSITION_CHAIN_END) { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition = content::PageTransitionFromInt( 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & ~content::PAGE_TRANSITION_CHAIN_END); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t redirect_index = 0; redirect_index < redirects.size(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_index++) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt(stripped_transition | redirect_info); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the last transition, add a CHAIN_END marker 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirect_index == (redirects.size() - 1)) { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = content::PageTransitionFromInt( 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t | content::PAGE_TRANSITION_CHAIN_END); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record all redirect visits with the same timestamp. We don't display 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them anyway, and if we ever decide to, we can reconstruct their order 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the redirect chain. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(redirects[redirect_index], 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time, last_ids.second, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t, request.visit_source); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (t & content::PAGE_TRANSITION_CHAIN_START) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(redirects[redirect_index], 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_visit_id, last_ids.second, t, request.time); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the visit_details for this visit. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subsequent transitions in the redirect list must all be server 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_SERVER_REDIRECT; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last, save this redirect chain for later so we can set titles & favicons 528bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // on the redirected pages properly. 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_.Put(request.url, redirects); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the last visit to the tracker so we can get outgoing transitions. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): Due to http://b/1194536 we lose the referrers of a subframe 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation anyway, so last_visit_id is always zero for them. But adding 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them here confuses main frame history, so we skip them for now. 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stripped_transition != content::PAGE_TRANSITION_AUTO_SUBFRAME && 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition != content::PAGE_TRANSITION_MANUAL_SUBFRAME && 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.AddVisit(request.id_scope, request.page_id, request.url, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::InitImpl(const std::string& languages) { 550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!db_) << "Initializing HistoryBackend twice"; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the rare case where the db fails to initialize a dialog may get shown 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the blocks the caller, yet allows other messages through. For this reason 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only set db_ to the created database if creation is successful. That 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way other methods won't do anything as db_ is still NULL. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 558bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Compute the file names. 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath history_name = history_dir_.Append(chrome::kHistoryFilename); 5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::FilePath thumbnail_name = GetFaviconsFileName(); 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_name = GetArchivedFileName(); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 563bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete the old index database files which are no longer used. 564bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeleteFTSIndexDatabases(); 565bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History database. 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new HistoryDatabase()); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Unretained to avoid a ref loop with db_. 5707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) db_->set_error_callback( 5717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::DatabaseErrorCallback, 5727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Unretained(this))); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sql::InitStatus status = db_->Init(history_name); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_OK: 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_FAILURE: { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A NULL db_ will cause all calls on this object to notice this error 5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and to not continue. If the error callback scheduled killing the 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database, the task it posted has not executed yet. Try killing the 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database now before we close it. 5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool kill_db = scheduled_kill_db_; 5847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (kill_db) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KillHistoryDatabase(); 5867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.AttemptedToFixProfileError", kill_db); 587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->NotifyProfileError(status); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill the in-memory database and send it back to the history service on the 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main thread. 597a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<InMemoryHistoryBackend> mem_backend(new InMemoryHistoryBackend); 599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (mem_backend->Init(history_name, db_.get())) 600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->SetInMemoryBackend(mem_backend.Pass()); 601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginExclusiveMode(); // Must be after the mem backend read the data. 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thumbnail database. 6053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): "thumbnail database" these days only stores 6063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // favicons. Thumbnails are stored in "top sites". Consider 6073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // renaming "thumbnail" references to "favicons" or something of the 6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // sort. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(new ThumbnailDatabase()); 6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (thumbnail_db_->Init(thumbnail_name) != sql::INIT_OK) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unlike the main database, we don't error out when the database is too 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new because this error is much less severe. Generally, this shouldn't 61358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // happen since the thumbnail and main database versions should be in sync. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll just continue without thumbnails & favicons in this case or any 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other error. 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the thumbnail database."; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Archived database. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->needs_version_17_migration()) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See needs_version_17_migration() decl for more. In this case, we want 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to delete the archived database and need to do so before we try to 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // open the file. We can ignore any error (maybe the file doesn't exist). 625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_name); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_name)) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Generate the history and thumbnail database metrics only after performing 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any migration work. 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::RandInt(1, 100) == 50) { 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only do this computation sometimes since it can be expensive. 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->ComputeDatabaseMetrics(history_name); 6382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (thumbnail_db_) 6392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch thumbnail_db_->ComputeDatabaseMetrics(); 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the expiration module about all the nice databases we made. This must 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen before db_->Init() is called since the callback ForceArchiveHistory 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may need to expire stuff. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *sigh*, this can all be cleaned up when that migration code is removed. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The main DB initialization should intuitively be first (not that it 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually matters) and the expirer should be set last. 64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) expirer_.SetDatabases(db_.get(), archived_db_.get(), thumbnail_db_.get()); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the long-running transaction. 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the first item in our database. 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start expiring old stuff. 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.StartArchivingOldStuff(TimeDelta::FromDays(kArchiveDaysThreshold)); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 665b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(new AndroidProviderBackend( 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAndroidCacheFileName(), db_.get(), thumbnail_db_.get(), 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_, delegate_.get())); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HISTOGRAM_TIMES("History.InitTime", 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HistoryBackend::OnMemoryPressure( 677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool trim_aggressively = memory_pressure_level == 679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 680ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (db_) 681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_->TrimMemory(trim_aggressively); 682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (thumbnail_db_) 683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch thumbnail_db_->TrimMemory(trim_aggressively); 684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (archived_db_) 685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch archived_db_->TrimMemory(trim_aggressively); 686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloseAllDatabases() { 689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit the long-running transaction. 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 69358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Forget the first recorded time since the database is closed. 69458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) first_recorded_time_ = base::Time(); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time time, 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID referring_visit, 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top-level frame navigations are visible, everything else is hidden 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool new_hidden = !content::PageTransitionIsMainFrame(transition); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This code must stay in sync with 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExpireHistoryBackend::ExpireURLsForVisits(). 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typed, which would eliminate the need for this code. 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int typed_increment = 0; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type = 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((transition_type == content::PAGE_TRANSITION_TYPED && 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !content::PageTransitionIsRedirect(transition)) || 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED) 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typed_increment = 1; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only count the page visit if it came from user browsing and only count it 729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // once when cycling through a redirect chain. 730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_source == SOURCE_BROWSED && 731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) { 732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordTopPageVisitStats(url); 733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if this URL is already in the DB. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update of an existing row. 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionStripQualifier(transition) != 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_RELOAD) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(url_info.visit_count() + 1); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typed_increment) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(url_info.typed_count() + typed_increment); 746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_info.last_visit() < time) 747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_info.set_last_visit(time); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow un-hiding of pages, never hiding. 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_hidden) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(url_id, url_info); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Addition of a new row. 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(1); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(typed_increment); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(time); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(new_hidden); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = db_->AddURL(url_info); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding URL failed."; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(0, 0); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.id_ = url_id; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the visit with the time to the database. 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification of the visit. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id) { 779b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 780b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlVisited(transition, &url_info); 781b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLVisitedDetails> details(new URLVisitedDetails); 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->transition = transition; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->row = url_info; 785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) details->visit_time = time; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetMostRecentRedirectsTo(url, &details->redirects); 789a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, 790a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 8050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<URLsModifiedDetails> modified_in_archive(new URLsModifiedDetails); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will add to either the archived database or the main one depending on 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the date of the added visit. 8110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLDatabase* url_database = NULL; 8120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch VisitDatabase* visit_database = NULL; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) { 814b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!archived_db_) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No archived database to save it to, just forget this. 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = archived_db_.get(); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = archived_db_.get(); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = db_.get(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = db_.get(); 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = url_database->AddURL(*i); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->typed_count() > 0) { 8340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Collect expired URLs that belong to |archived_db_| separately; we 8350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // want to fire NOTIFICATION_HISTORY_URLS_MODIFIED only for changes that 8360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // take place in the main |db_|. 8370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url_database == db_.get()) { 8380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified->changed_urls.push_back(*i); 8390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0. 8400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 8410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified_in_archive->changed_urls.push_back(*i); 8420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified_in_archive->changed_urls.back().set_id(url_id); 8430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_database->AddVisit(&visit_info, visit_source)) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) { 8670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified( 8680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &modified_in_archive->changed_urls); 869b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 8700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 871b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modified.PassAs<HistoryDetails>()); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return time < expirer_.GetCurrentArchiveTime(); 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 888a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 889b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 925b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 926b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 928a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 935b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_info.set_title(base::UTF8ToUTF16(url.spec())); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 961b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 976b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 982b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 990b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 996b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->UpdateURLRow(id, url); 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 1004b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 1019b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 1029b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 1037b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryURL(scoped_refptr<QueryURLRequest> request, 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool want_visits) { 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow* row = &request->value.a; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits = &request->value.b; 1051b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForURL(url, row)) { 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have a row. 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = true; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optionally query the visits. 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (want_visits) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(row->id(), visits); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, row, visits); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1064b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1065b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1066b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1067b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment usage --------------------------------------------------------------- 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteOldSegmentData() { 1071b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteSegmentData(Time::Now() - 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kSegmentDataRetention)); 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QuerySegmentUsage( 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time from_time, 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_result_count) { 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1083b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the first time we query segments, invoke 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteOldSegmentData asynchronously. We do this to cleanup old 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries. 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!segment_queried_) { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_ = true; 109190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HistoryBackend::DeleteOldSegmentData, this)); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& term) { 1104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 11080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLRow row; 11090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!db_->GetRowForURL(url, &row)) { 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->SetKeywordSearchTermsForURL(row.id(), keyword_id, term); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 11180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, 1119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails>( 11200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new KeywordSearchUpdatedDetails(row, keyword_id, term))); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllSearchTermsForKeyword( 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id) { 1126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): bug 1168470. Need to move from archive dbs too. 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetMostRecentKeywordSearchTerms( 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& prefix, 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_count) { 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(request->value)); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HistoryBackend::DeleteKeywordSearchTermForURL(const GURL& url) { 11500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!db_) 11510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 11540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!url_id) 11550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) db_->DeleteKeywordSearchTermForURL(url_id); 11570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BroadcastNotifications( 11590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, 11600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<HistoryDetails>(new KeywordSearchDeletedDetails(url_id))); 11610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleCommit(); 11620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 11630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HistoryBackend::DeleteMatchingURLsForKeyword(TemplateURLID keyword_id, 11655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& term) { 11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_) 11675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 11685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<KeywordSearchTermRow> rows; 11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_->GetKeywordSearchTermRows(term, &rows)) { 11715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<GURL> items_to_delete; 11725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLRow row; 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<KeywordSearchTermRow>::iterator it = rows.begin(); 11745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != rows.end(); ++it) { 11755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((it->keyword_id == keyword_id) && db_->GetURLRow(it->url_id, &row)) 11765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) items_to_delete.push_back(row.url()); 11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteURLs(items_to_delete); 11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)uint32 HistoryBackend::GetNextDownloadId() { 1185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return db_ ? db_->GetNextDownloadId() : content::DownloadItem::kInvalidId; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HistoryBackend::CreateDownload(const history::DownloadRow& history_info) { 1203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 1204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool success = db_->CreateDownload(history_info); 12062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 1207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return success; 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 12177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 12187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 12237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 12247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 12267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 12277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 12297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 12307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 12317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 12327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 12337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 12347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 12357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 12387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 12397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 12417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 1245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options) { 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now query the archived database. This is a bit tricky because we don't 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to query it if the queried time range isn't going to find anything 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in it. 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1171036: do blimpie querying for the archived database 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as well. 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if (archived_db_.get() && 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) { 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 1266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(db_.get(), db_.get(), text_query, options, 1267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &request->value); 1268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (archived_db_.get() && 1269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expirer_.GetCurrentArchiveTime() >= options.begin_time) { 1270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query, 1271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options, &request->value); 1272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_db, 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options, 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); 12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_db->GetURLRow(visit.url_id, &url_result)) { 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The archived database may be out of sync with respect to starring, 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // titles, last visit date, etc. Therefore, we query the main DB if the 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current URL database is not the main one. 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_db == db_.get()) { 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently querying the archived DB, update with the main database to 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch any interesting stuff. This will update it if it exists in the 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main DB, and do nothing otherwise. 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForURL(url_result.url(), &url_result); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 1338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::QueryHistoryText(URLDatabase* url_db, 1339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitDatabase* visit_db, 1340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 1341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 1344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_db->GetTextMatches(text_query, &text_matches); 1345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) visit_db->GetVisibleVisitsForURL(text_match.id(), options, &visits); 1352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Frontend to GetMostRecentRedirectsFrom from the history thread. 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsFrom( 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsFrom(url, &request->value); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsTo( 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsTo(url, &request->value); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetVisibleVisitCountToHostRequest> request, 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time first_visit; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = db_.get() && 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisibleVisitCountToHost(url, &count, &first_visit); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, count, first_visit); 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryTopURLsAndRedirects( 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count) { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), false, NULL, NULL); 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL>* top_urls = &request->value.a; 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectMap* redirects = &request->value.b; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_urls->push_back(data[i]->GetURL()); 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*redirects)[top_urls->back()] = list; 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), true, top_urls, redirects); 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will replace QueryTopURLsAndRedirectsRequest. 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLs( 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryMostVisitedURLsRequest> request, 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back) { 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), MostVisitedURLList()); 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result = &request->value; 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryMostVisitedURLsImpl(result_count, days_back, result); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), *result); 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryFilteredURLs( 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryFilteredURLsRequest> request, 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::VisitFilter& filter, 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool extended_info) { 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1462b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), FilteredURLList()); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURLList& result = request->value; 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.push_back(url); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), result); 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back, 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result) { 1538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromDays(days_back), 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects; 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(url); 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsFrom( 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& from_url, 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID from_url_id = db_->GetRowForURL(from_url, NULL); 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(cur_visit, redirects); 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsTo( 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& to_url, 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID to_url_id = db_->GetRowForURL(to_url, NULL); 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsToSpecificVisit(cur_visit, redirects); 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryURLProviderParams* params) { 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExecuteWithDB should handle the NULL database case. 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->ExecuteWithDB(this, db_.get(), params); 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1633bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1634bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1635bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1636bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1637bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1638bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1639bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1640bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1641bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1642bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1643bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1644bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1645bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1646bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1647bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1648bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1649bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 16542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 16550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, 16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 16582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryBackend::GetLargestFaviconForURL( 16620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& page_url, 16630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<int>& icon_types, 16640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int minimum_size_in_pixels, 16650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult* favicon_bitmap_result) { 16668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(favicon_bitmap_result); 16678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!db_ || !thumbnail_db_) 16698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 16728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 16748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings) || 16758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) icon_mappings.empty()) 16768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int required_icon_types = 0; 16798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator i = icon_types.begin(); 16808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_types.end(); ++i) { 16818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) required_icon_types |= *i; 16828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find the largest bitmap for each IconType placing in 16858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // |largest_favicon_bitmaps|. 16860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::map<favicon_base::IconType, FaviconBitmap> largest_favicon_bitmaps; 16878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<IconMapping>::const_iterator i = icon_mappings.begin(); 16888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_mappings.end(); ++i) { 16898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!(i->icon_type & required_icon_types)) 16908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 16918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 16928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(i->icon_id, &bitmap_id_sizes); 16938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap& largest = largest_favicon_bitmaps[i->icon_type]; 16948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<FaviconBitmapIDSize>::const_iterator j = 16958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_id_sizes.begin(); j != bitmap_id_sizes.end(); ++j) { 16968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest.bitmap_id == 0 || 16978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest.pixel_size.width() < j->pixel_size.width() && 16988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size.height() < j->pixel_size.height())) { 16998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.icon_id = i->icon_id; 17008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.bitmap_id = j->bitmap_id; 17018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size = j->pixel_size; 17028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_favicon_bitmaps.empty()) 17068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find an icon which is larger than minimum_size_in_pixels in the order of 17098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // icon_types. 17108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap largest_icon; 17118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator t = icon_types.begin(); 17128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) t != icon_types.end(); ++t) { 17130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::map<favicon_base::IconType, FaviconBitmap>::const_iterator f = 17140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest_favicon_bitmaps.begin(); 17150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f != largest_favicon_bitmaps.end(); 17160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++f) { 17178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (f->first & *t && 17188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.bitmap_id == 0 || 17198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.pixel_size.height() < f->second.pixel_size.height() && 17208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.width() < f->second.pixel_size.width()))) { 17218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon = f->second; 17228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_icon.pixel_size.width() > minimum_size_in_pixels && 17258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.height() > minimum_size_in_pixels) 17268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 17278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL icon_url; 17300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 17318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(largest_icon.icon_id, &icon_url, 17328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &icon_type)) { 17338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::Time last_updated; 17370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult bitmap_result; 17388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_url = icon_url; 17398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_type = icon_type; 17408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(largest_icon.bitmap_id, 17418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &last_updated, 17428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.bitmap_data, 17438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.pixel_size)) { 17448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 17488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 17498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (bitmap_result.is_valid()) 17508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *favicon_bitmap_result = bitmap_result; 17518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) HISTOGRAM_TIMES("History.GetLargestFaviconForURL", 17538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks::Now() - beginning_time); 17548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 17558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 17610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, 17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 17680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id, 17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 17702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScaleFactor desired_scale_factor, 17710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ui::ScaleFactor> desired_scale_factors; 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors.push_back(desired_scale_factor); 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, 17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, 17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 17900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 17990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 180690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 18382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 186058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Initial State: www.google.com/favicon.ico 16x16, 32x32 18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 18692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 188058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Difficulty 1: All but news.google.com/news_specific.ico are unmapped from 18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 19232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 19260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 19272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 19332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 19390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 19400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapData>& favicon_bitmap_data) { 1941b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build map of FaviconBitmapData for each icon url. 19470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef std::map<GURL, std::vector<favicon_base::FaviconBitmapData> > 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> icon_ids; 19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 19630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id = 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 19652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 19682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 1969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1994b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 2008b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 2021b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 20300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 20310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch thumbnail_db_->GetFaviconIDForFaviconURL( 20320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_usage[i].favicon_url, favicon_base::FAVICON, NULL); 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 20380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON, 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service && bookmark_service_->IsBookmarked(*url)) { 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 206690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 20670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *url, favicon_base::FAVICON, NULL)) { 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 2079a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details( 2080a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new FaviconChangedDetails); 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2083a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 20930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 20960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!page_url || icon_types == favicon_base::FAVICON || 20970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_ICON || 20980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_PRECOMPOSED_ICON || 20990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == 21000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON)); 21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 21110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType selected_icon_type = favicon_base::INVALID_ICON; 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 21150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type_out; 21160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconID favicon_id = 211790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 211890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, 21442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 21480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id, 21490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapData>& favicon_bitmap_data, 21502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 21512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 21532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapData> to_add = favicon_bitmap_data; 21582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 21602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 21610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapData>::iterator match_it = 21620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.end(); 21630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<favicon_base::FaviconBitmapData>::iterator it = 21640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.begin(); 21650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != to_add.end(); 21660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 21672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 21682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 21742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 21752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 21762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 21822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 21832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 21842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 21852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 21862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 21972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 21982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool HistoryBackend::ValidateSetFaviconsParams(const std::vector< 22060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapData>& favicon_bitmap_data) const { 22072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 22142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 22162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 22212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 22242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 22252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 22332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 22352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 22382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 22392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 22402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 22422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 22500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) { 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 22522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 22640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 22692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 22702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, favicon_bitmap_results); 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 22732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 22770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& candidate_favicon_ids, 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 22800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) { 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 22900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID best_favicon_id = 0; 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors, 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_size_in_dip, 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct FaviconBitmapResults from |best_favicon_id| and 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 23250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 23330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult bitmap_result; 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 23540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 2355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 23760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> unmapped_icon_ids = icon_ids; 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 23970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID>::iterator icon_id_it = std::find( 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((icon_type == favicon_base::TOUCH_ICON && 24070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON) || 24080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON && 24090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_ICON) || 24100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == m->icon_type)) { 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details(new FaviconChangedDetails); 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 249290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.front()->Release(); 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_task_requests_.empty()) 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDBTaskRequest* request = db_task_requests_.front(); 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->value->RunOnDBThread(this, db_.get())) { 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task is done. Notify the callback. 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(); 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We AddRef'd the request before adding, need to release it now. 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Release(); 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tasks wants to run some more. Schedule it at the end of current tasks. 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request); 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And process it after an invoke later. 253290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ReleaseDBTasks() { 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::list<HistoryDBTaskRequest*>::iterator i = 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.clear(); 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 257358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!db_) 257458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 257758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) restrict_urls.empty()) { 257858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 257958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // possibility of an information leak. 258058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DeleteAllHistory(); 258158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 258258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Clearing parts of history, have the expirer do the depend 258358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 258458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 258558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 258658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // we want to get it on disk ASAP. 258758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Commit(); 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 25952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 25962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 25982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 26012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 26062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 26082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 26092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 26102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 26112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 26122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &results); 26132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 26162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 26182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 26192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 26212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 26222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 26242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 26252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 26272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 26282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 26312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 26322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 26332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 26342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 26352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 26362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 26372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 26392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 26402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 26412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 26442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 26452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 26462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 26502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 26522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 26532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 26552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 26562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 26642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 26652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 26877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 26887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 26897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 26907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 26917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 26927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 26937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 26947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 26957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 26967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 26977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 26987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 27007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2701b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 2717bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch expirer_.SetDatabases(NULL, NULL, NULL); 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryDBTaskRequest> request) { 2726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(request.get()); 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_scheduled = !db_task_requests_.empty(); 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we up the refcount of the request. ProcessDBTaskImpl will 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release when done with the task. 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AddRef(); 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request.get()); 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!task_scheduled) { 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other tasks are scheduled. Process request now. 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 2743a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails> details) { 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2746b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 2747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->BroadcastNotifications(type, details.Pass()); 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid HistoryBackend::NotifySyncURLsModified(URLRows* rows) { 27510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) 27520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified(rows); 27530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 27540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 2756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool archived, 2757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 2759b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, archived, rows); 2760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2761b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BookmarkService::URLAndTitle> starred_urls; 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service) 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->GetBookmarks(&starred_urls); 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 27983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!ClearAllThumbnailHistory(kept_urls)) { 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 280458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 280558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Therefore, we clear the list afterwards to make sure nobody uses this 280658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // invalid data. 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2811bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete archived history. 2812b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the database and delete the file. 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_file_name = GetArchivedFileName(); 2816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_file_name); 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now re-initialize the database (which may fail). 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_file_name)) { 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open our long-running transaction on this database. 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 283158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Send out the notification that history is cleared. The in-memory database 28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 2833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2835b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 2836a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2837a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(const URLRows& kept_urls) { 2841b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 28463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sql::Connection::Delete(GetFaviconsFileName()); 28473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 28483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Older version of the database. 2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Urls to retain mappings for. 28543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<GURL> urls_to_keep; 28553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); 28563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) i != kept_urls.end(); ++i) { 28573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) urls_to_keep.push_back(i->url()); 28583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Isolate from any long-running transaction. 28613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 28623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): If this fails, perhaps the database should be razed 28653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or deleted. 28663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!thumbnail_db_->RetainDataForPageUrls(urls_to_keep)) { 28673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->RollbackTransaction(); 28683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 289358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Insert the URLs into the temporary table. 28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 289658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) db_->AddTemporaryURL(*i); 28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkService* HistoryBackend::GetBookmarkService() { 29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service_) 29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->BlockTillLoaded(); 29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bookmark_service_; 29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2930b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention, 2938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &most_visited_urls); 2939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 2950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 2952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 2953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 2955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 2959