history_backend.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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" 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/bookmarks/core/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); 408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (origin_url.SchemeIs(content::kHttpScheme) || 409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) origin_url.SchemeIs(content::kHttpsScheme) || 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin_url.SchemeIs(content::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; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetMostRecentRedirectsTo(url, &details->redirects); 788a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, 789a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 8040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<URLsModifiedDetails> modified_in_archive(new URLsModifiedDetails); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will add to either the archived database or the main one depending on 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the date of the added visit. 8100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLDatabase* url_database = NULL; 8110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch VisitDatabase* visit_database = NULL; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) { 813b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!archived_db_) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No archived database to save it to, just forget this. 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = archived_db_.get(); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = archived_db_.get(); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = db_.get(); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = db_.get(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = url_database->AddURL(*i); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->typed_count() > 0) { 8330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Collect expired URLs that belong to |archived_db_| separately; we 8340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // want to fire NOTIFICATION_HISTORY_URLS_MODIFIED only for changes that 8350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // take place in the main |db_|. 8360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url_database == db_.get()) { 8370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified->changed_urls.push_back(*i); 8380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0. 8390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 8400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified_in_archive->changed_urls.push_back(*i); 8410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch modified_in_archive->changed_urls.back().set_id(url_id); 8420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_database->AddVisit(&visit_info, visit_source)) { 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) { 8660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified( 8670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &modified_in_archive->changed_urls); 868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 8690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 870b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modified.PassAs<HistoryDetails>()); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return time < expirer_.GetCurrentArchiveTime(); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 886a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 888b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 924b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 925b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 927a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 934b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_info.set_title(base::UTF8ToUTF16(url.spec())); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 95890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 960b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 975b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 981b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 989b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 995b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->UpdateURLRow(id, url); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 1003b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 1018b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 1028b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 1036b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryURL(scoped_refptr<QueryURLRequest> request, 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool want_visits) { 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow* row = &request->value.a; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits = &request->value.b; 1050b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForURL(url, row)) { 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have a row. 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = true; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optionally query the visits. 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (want_visits) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(row->id(), visits); 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, row, visits); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1063b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1064b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1065b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1066b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment usage --------------------------------------------------------------- 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteOldSegmentData() { 1070b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteSegmentData(Time::Now() - 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kSegmentDataRetention)); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QuerySegmentUsage( 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time from_time, 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_result_count) { 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1082b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the first time we query segments, invoke 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteOldSegmentData asynchronously. We do this to cleanup old 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries. 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!segment_queried_) { 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_ = true; 109090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HistoryBackend::DeleteOldSegmentData, this)); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& term) { 1103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 11070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLRow row; 11080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!db_->GetRowForURL(url, &row)) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->SetKeywordSearchTermsForURL(row.id(), keyword_id, term); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 11170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, 1118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails>( 11190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new KeywordSearchUpdatedDetails(row, keyword_id, term))); 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllSearchTermsForKeyword( 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id) { 1125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): bug 1168470. Need to move from archive dbs too. 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetMostRecentKeywordSearchTerms( 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& prefix, 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_count) { 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(request->value)); 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HistoryBackend::DeleteKeywordSearchTermForURL(const GURL& url) { 11490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!db_) 11500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 11530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!url_id) 11540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) db_->DeleteKeywordSearchTermForURL(url_id); 11560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BroadcastNotifications( 11580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, 11590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<HistoryDetails>(new KeywordSearchDeletedDetails(url_id))); 11600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleCommit(); 11610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 11620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HistoryBackend::DeleteMatchingURLsForKeyword(TemplateURLID keyword_id, 11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& term) { 11655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_) 11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 11675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<KeywordSearchTermRow> rows; 11695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_->GetKeywordSearchTermRows(term, &rows)) { 11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<GURL> items_to_delete; 11715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLRow row; 11725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<KeywordSearchTermRow>::iterator it = rows.begin(); 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != rows.end(); ++it) { 11745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((it->keyword_id == keyword_id) && db_->GetURLRow(it->url_id, &row)) 11755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) items_to_delete.push_back(row.url()); 11765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteURLs(items_to_delete); 11785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)uint32 HistoryBackend::GetNextDownloadId() { 1184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return db_ ? db_->GetNextDownloadId() : content::DownloadItem::kInvalidId; 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HistoryBackend::CreateDownload(const history::DownloadRow& history_info) { 1202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 1203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool success = db_->CreateDownload(history_info); 12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 1206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return success; 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 12167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 12177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 12227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 12237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 12257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 12267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 12287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 12297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 12307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 12317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 12327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 12337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 12347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 12377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 12387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 12407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 1244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options) { 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now query the archived database. This is a bit tricky because we don't 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to query it if the queried time range isn't going to find anything 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in it. 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1171036: do blimpie querying for the archived database 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as well. 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if (archived_db_.get() && 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) { 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(db_.get(), db_.get(), text_query, options, 1266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &request->value); 1267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (archived_db_.get() && 1268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expirer_.GetCurrentArchiveTime() >= options.begin_time) { 1269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query, 1270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options, &request->value); 1271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_db, 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options, 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); 12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_db->GetURLRow(visit.url_id, &url_result)) { 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The archived database may be out of sync with respect to starring, 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // titles, last visit date, etc. Therefore, we query the main DB if the 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current URL database is not the main one. 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_db == db_.get()) { 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently querying the archived DB, update with the main database to 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch any interesting stuff. This will update it if it exists in the 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main DB, and do nothing otherwise. 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForURL(url_result.url(), &url_result); 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 1337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::QueryHistoryText(URLDatabase* url_db, 1338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitDatabase* visit_db, 1339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 1340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 1343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_db->GetTextMatches(text_query, &text_matches); 1344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 13504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) visit_db->GetVisibleVisitsForURL(text_match.id(), options, &visits); 1351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Frontend to GetMostRecentRedirectsFrom from the history thread. 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsFrom( 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsFrom(url, &request->value); 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsTo( 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsTo(url, &request->value); 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetVisibleVisitCountToHostRequest> request, 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time first_visit; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = db_.get() && 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisibleVisitCountToHost(url, &count, &first_visit); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, count, first_visit); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryTopURLsAndRedirects( 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count) { 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), false, NULL, NULL); 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL>* top_urls = &request->value.a; 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectMap* redirects = &request->value.b; 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_urls->push_back(data[i]->GetURL()); 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*redirects)[top_urls->back()] = list; 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), true, top_urls, redirects); 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will replace QueryTopURLsAndRedirectsRequest. 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLs( 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryMostVisitedURLsRequest> request, 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back) { 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), MostVisitedURLList()); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result = &request->value; 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryMostVisitedURLsImpl(result_count, days_back, result); 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), *result); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryFilteredURLs( 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryFilteredURLsRequest> request, 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::VisitFilter& filter, 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool extended_info) { 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), FilteredURLList()); 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURLList& result = request->value; 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.push_back(url); 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), result); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back, 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result) { 1537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromDays(days_back), 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects; 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(url); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsFrom( 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& from_url, 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID from_url_id = db_->GetRowForURL(from_url, NULL); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(cur_visit, redirects); 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsTo( 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& to_url, 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID to_url_id = db_->GetRowForURL(to_url, NULL); 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsToSpecificVisit(cur_visit, redirects); 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryURLProviderParams* params) { 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExecuteWithDB should handle the NULL database case. 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->ExecuteWithDB(this, db_.get(), params); 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1632bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1633bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1634bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1635bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1636bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1637bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1638bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1639bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1640bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1641bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1642bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1643bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1644bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1645bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1646bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1647bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1648bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 16540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 16552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, 16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryBackend::GetLargestFaviconForURL( 16610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& page_url, 16620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<int>& icon_types, 16630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int minimum_size_in_pixels, 16640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult* favicon_bitmap_result) { 16658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(favicon_bitmap_result); 16668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!db_ || !thumbnail_db_) 16688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 16718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 16738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings) || 16748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) icon_mappings.empty()) 16758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int required_icon_types = 0; 16788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator i = icon_types.begin(); 16798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_types.end(); ++i) { 16808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) required_icon_types |= *i; 16818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find the largest bitmap for each IconType placing in 16848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // |largest_favicon_bitmaps|. 16850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::map<favicon_base::IconType, FaviconBitmap> largest_favicon_bitmaps; 16868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<IconMapping>::const_iterator i = icon_mappings.begin(); 16878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_mappings.end(); ++i) { 16888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!(i->icon_type & required_icon_types)) 16898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 16908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 16918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(i->icon_id, &bitmap_id_sizes); 16928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap& largest = largest_favicon_bitmaps[i->icon_type]; 16938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<FaviconBitmapIDSize>::const_iterator j = 16948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_id_sizes.begin(); j != bitmap_id_sizes.end(); ++j) { 16958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest.bitmap_id == 0 || 16968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest.pixel_size.width() < j->pixel_size.width() && 16978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size.height() < j->pixel_size.height())) { 16988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.icon_id = i->icon_id; 16998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.bitmap_id = j->bitmap_id; 17008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size = j->pixel_size; 17018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_favicon_bitmaps.empty()) 17058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find an icon which is larger than minimum_size_in_pixels in the order of 17088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // icon_types. 17098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap largest_icon; 17108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator t = icon_types.begin(); 17118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) t != icon_types.end(); ++t) { 17120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::map<favicon_base::IconType, FaviconBitmap>::const_iterator f = 17130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest_favicon_bitmaps.begin(); 17140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f != largest_favicon_bitmaps.end(); 17150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++f) { 17168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (f->first & *t && 17178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.bitmap_id == 0 || 17188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.pixel_size.height() < f->second.pixel_size.height() && 17198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.width() < f->second.pixel_size.width()))) { 17208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon = f->second; 17218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_icon.pixel_size.width() > minimum_size_in_pixels && 17248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.height() > minimum_size_in_pixels) 17258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 17268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL icon_url; 17290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 17308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(largest_icon.icon_id, &icon_url, 17318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &icon_type)) { 17328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::Time last_updated; 17360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult bitmap_result; 17378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_url = icon_url; 17388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_type = icon_type; 17398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(largest_icon.bitmap_id, 17408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &last_updated, 17418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.bitmap_data, 17428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.pixel_size)) { 17438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 17448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 17458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 17478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 17488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (bitmap_result.is_valid()) 17498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *favicon_bitmap_result = bitmap_result; 17508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) HISTOGRAM_TIMES("History.GetLargestFaviconForURL", 17528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks::Now() - beginning_time); 17538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 17548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 17600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, 17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 17670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id, 17682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScaleFactor desired_scale_factor, 17700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ui::ScaleFactor> desired_scale_factors; 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors.push_back(desired_scale_factor); 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, 17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, 17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 17890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 17980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 180590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 18382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 185958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Initial State: www.google.com/favicon.ico 16x16, 32x32 18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 18692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 187958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Difficulty 1: All but news.google.com/news_specific.ico are unmapped from 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 19232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 19250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 19380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 19390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapData>& favicon_bitmap_data) { 1940b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build map of FaviconBitmapData for each icon url. 19460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef std::map<GURL, std::vector<favicon_base::FaviconBitmapData> > 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> icon_ids; 19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 19620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id = 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 1968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1993b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 2007b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 2020b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 20290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 20300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch thumbnail_db_->GetFaviconIDForFaviconURL( 20310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_usage[i].favicon_url, favicon_base::FAVICON, NULL); 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 20370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON, 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service && bookmark_service_->IsBookmarked(*url)) { 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 206590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 20660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *url, favicon_base::FAVICON, NULL)) { 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 2078a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details( 2079a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new FaviconChangedDetails); 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2082a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 20920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* bitmap_results) { 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 20950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!page_url || icon_types == favicon_base::FAVICON || 20960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_ICON || 20970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_PRECOMPOSED_ICON || 20980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == 20990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON)); 21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 21100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType selected_icon_type = favicon_base::INVALID_ICON; 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 21140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type_out; 21150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconID favicon_id = 211690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 211790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, 21432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 21470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id, 21480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapData>& favicon_bitmap_data, 21492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 21502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 21522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapData> to_add = favicon_bitmap_data; 21572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 21592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 21600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapData>::iterator match_it = 21610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.end(); 21620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<favicon_base::FaviconBitmapData>::iterator it = 21630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.begin(); 21640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != to_add.end(); 21650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 21662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 21672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 21732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 21742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 21752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 21802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 21822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 21832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 21842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 21852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 21862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 21962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 21972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 22002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool HistoryBackend::ValidateSetFaviconsParams(const std::vector< 22050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapData>& favicon_bitmap_data) const { 22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 22072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 22132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 22142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 22162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 22202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 22232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 22242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 22312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 22342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 22372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 22382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 22392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 22402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 22490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) { 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 22512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 22630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 22682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 22692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, favicon_bitmap_results); 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 22722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 22760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& candidate_favicon_ids, 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 22790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) { 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 22890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID best_favicon_id = 0; 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors, 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_size_in_dip, 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct FaviconBitmapResults from |best_favicon_id| and 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 23240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 23320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult bitmap_result; 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 23530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 2354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 23750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> unmapped_icon_ids = icon_ids; 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 23960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID>::iterator icon_id_it = std::find( 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((icon_type == favicon_base::TOUCH_ICON && 24060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON) || 24070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON && 24080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_ICON) || 24090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == m->icon_type)) { 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details(new FaviconChangedDetails); 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 249190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.front()->Release(); 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_task_requests_.empty()) 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDBTaskRequest* request = db_task_requests_.front(); 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->value->RunOnDBThread(this, db_.get())) { 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task is done. Notify the callback. 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(); 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We AddRef'd the request before adding, need to release it now. 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Release(); 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tasks wants to run some more. Schedule it at the end of current tasks. 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request); 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And process it after an invoke later. 253190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ReleaseDBTasks() { 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::list<HistoryDBTaskRequest*>::iterator i = 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.clear(); 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 257258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!db_) 257358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 257658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) restrict_urls.empty()) { 257758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 257858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // possibility of an information leak. 257958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DeleteAllHistory(); 258058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 258158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Clearing parts of history, have the expirer do the depend 258258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 258358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 258458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 258558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // we want to get it on disk ASAP. 258658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Commit(); 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 25942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 25952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 25972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 26002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 26012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 26072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 26082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 26092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 26102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 26112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &results); 26122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 26142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 26172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 26182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 26202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 26212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 26232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 26242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 26262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 26272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 26302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 26312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 26322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 26332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 26342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 26352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 26362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 26382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 26392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 26402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 26432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 26442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 26452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 26492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 26512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 26522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 26542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 26552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 26582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 26632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 26642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 26867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 26877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 26887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 26897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 26907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 26917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 26927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 26937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 26947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 26957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 26967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 26977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 26997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 2716bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch expirer_.SetDatabases(NULL, NULL, NULL); 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryDBTaskRequest> request) { 2725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(request.get()); 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_scheduled = !db_task_requests_.empty(); 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we up the refcount of the request. ProcessDBTaskImpl will 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release when done with the task. 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AddRef(); 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request.get()); 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!task_scheduled) { 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other tasks are scheduled. Process request now. 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 2742a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails> details) { 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 2746a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->BroadcastNotifications(type, details.Pass()); 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid HistoryBackend::NotifySyncURLsModified(URLRows* rows) { 27500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) 27510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified(rows); 27520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 27530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 2755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool archived, 2756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 2758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, archived, rows); 2759b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BookmarkService::URLAndTitle> starred_urls; 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service) 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->GetBookmarks(&starred_urls); 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 27973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!ClearAllThumbnailHistory(kept_urls)) { 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 280358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 280458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Therefore, we clear the list afterwards to make sure nobody uses this 280558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // invalid data. 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2810bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete archived history. 2811b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the database and delete the file. 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_file_name = GetArchivedFileName(); 2815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_file_name); 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now re-initialize the database (which may fail). 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_file_name)) { 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open our long-running transaction on this database. 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 283058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Send out the notification that history is cleared. The in-memory database 28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 2832a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2834b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 2835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2836a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(const URLRows& kept_urls) { 2840b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 28453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sql::Connection::Delete(GetFaviconsFileName()); 28463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 28473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Older version of the database. 2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Urls to retain mappings for. 28533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<GURL> urls_to_keep; 28543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); 28553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) i != kept_urls.end(); ++i) { 28563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) urls_to_keep.push_back(i->url()); 28573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Isolate from any long-running transaction. 28603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 28613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): If this fails, perhaps the database should be razed 28643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or deleted. 28653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!thumbnail_db_->RetainDataForPageUrls(urls_to_keep)) { 28663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->RollbackTransaction(); 28673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 289258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Insert the URLs into the temporary table. 28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 289558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) db_->AddTemporaryURL(*i); 28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkService* HistoryBackend::GetBookmarkService() { 29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service_) 29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->BlockTillLoaded(); 29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bookmark_service_; 29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2929b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention, 2937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &most_visited_urls); 2938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 2949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 2951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 2952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 2954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 2958