history_backend.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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" 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/history/core/browser/history_client.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/error_delegate_util.h" 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/android/android_provider_backend.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/* The HistoryBackend consists of two components: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase (stores past 3 months of history) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSegmentDatabase (stores groups of URLs for the most visited view). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExpireHistoryBackend (manages deleting things older than 3 months) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we keep segment data for in days. Currently 3 months. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This value needs to be greater or equal to 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependency between MostVisitedModel and the history backend. 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kSegmentDataRetention = 90; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we'll wait to do a commit, so that things are batched together. 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kCommitIntervalSeconds = 10; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time before we re-fetch the favicon. 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kFaviconRefetchDays = 7; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of items we'll allow in the redirect list before 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleting some. 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMaxRedirectCount = 32; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of days old a history entry can be before it is considered "old" 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// and is deleted. 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int kExpireDaysThreshold = 90; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of top sites to track when recording top page visit stats. 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const size_t kPageVisitStatsMaxTopSites = 50; 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts from PageUsageData to MostVisitedURL. |redirects| is a 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of redirects for this URL. Empty list means no redirects. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RedirectList& redirects) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL mv; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.url = page_data.GetURL(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.title = page_data.GetTitle(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects.empty()) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirects must contain at least the target url. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects = redirects; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last url must be the target url. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mv; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This task is run on a timer so that commits happen at regular intervals 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they are batched together. The important thing about this class is that 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it supports canceling of the task so the reference to the backend will be 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freed. The problem is that when history is shutting down, there is likely 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be one of these commits still pending and holding a reference. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backend can call Cancel to have this task release the reference. The 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task will still run (if we ever get to processing the event before 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown), but it will not do anything. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this is a refcounted object and is not a task in itself. It should 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be assigned to a RunnableMethod. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): bug 1165182: This should be replaced with a 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WeakPtrFactory which will handle everything automatically (like we do 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ExpireHistoryBackend). 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommitLaterTask : public base::RefCounted<CommitLaterTask> { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CommitLaterTask(HistoryBackend* history_backend) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : history_backend_(history_backend) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The backend will call this function if it is being destroyed so that we 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release our reference. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_ = NULL; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCommit() { 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (history_backend_.get()) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_->Commit(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<CommitLaterTask>; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CommitLaterTask() {} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryBackend> history_backend_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// HistoryBackend::QueryURLResult ---------------------------------------------- 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)HistoryBackend::QueryURLResult::QueryURLResult() : success(false) { 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)HistoryBackend::QueryURLResult::~QueryURLResult() { 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HistoryBackend -------------------------------------------------------------- 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistoryBackend::HistoryBackend(const base::FilePath& history_dir, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_dir_(history_dir), 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_(false), 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_(this, history_client), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_(kMaxRedirectCount), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_(NULL), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_(false), 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_(history_client) { 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) 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void HistoryBackend::ClearCachedDataForContextID(ContextID context_id) { 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tracker_.ClearCachedDataForContextID(context_id); 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) 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void HistoryBackend::UpdateWithPageEndTime(ContextID context_id, 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. 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VisitID visit_id = tracker_.GetLastVisit(context_id, 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( 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) request.context_id, request.page_id, request.referrer)); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit_id = last_ids.second; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a redirect chain is given, we expect the last item in that chain to be 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the final URL. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.redirects.empty() || 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects.back() == request.url); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is adding older history, we need to make sure our times 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are correct. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.time < first_recorded_time_) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = request.time; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition request_transition = request.transition; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition stripped_transition = 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(request_transition); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_generated = 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition == content::PAGE_TRANSITION_KEYWORD_GENERATED); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is navigating to a not-previously-typed intranet hostname, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the transition to TYPED so that the omnibox will learn that this is 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a known host. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_redirects = request.redirects.size() > 1; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionIsMainFrame(request_transition) && 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition != content::PAGE_TRANSITION_TYPED) && 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url(has_redirects ? 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects[0] : request.url); 408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (origin_url.SchemeIs(url::kHttpScheme) || 409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) origin_url.SchemeIs(url::kHttpsScheme) || 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) origin_url.SchemeIs(url::kFtpScheme)) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(origin_url.host()); 412a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t registry_length = 413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::GetRegistryLength( 414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) host, 415a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 416a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 417a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (registry_length == 0 && !db_->IsTypedHost(host)) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition = content::PAGE_TRANSITION_TYPED; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition = 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition | 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionGetQualifier(request_transition)); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_redirects) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The single entry is both a chain start and end. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = content::PageTransitionFromInt( 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition | 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect case (one element means just the page itself). 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(request.url, request.time, 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second, t, request.visit_source); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. KEYWORD_GENERATED visits should not 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result in changing most visited, so we don't update segments (most 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visited db). 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_keyword_generated) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(request.url, from_visit_id, last_ids.second, t, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the referrer's duration. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect case. Add the redirect chain. 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition redirect_info = 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects = request.redirects; 455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (redirects[0].SchemeIs(url::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) { 542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tracker_.AddVisit(request.context_id, 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) 62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Nuke any files corresponding to the legacy Archived History Database, which 62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // previously retained expired (> 3 months old) history entries, but, in the 62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // end, was not used for much, and consequently has been removed as of M37. 62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(engedy): Remove this code after the end of 2014. 62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sql::Connection::Delete(archived_name); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Generate the history and thumbnail database metrics only after performing 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any migration work. 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::RandInt(1, 100) == 50) { 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only do this computation sometimes since it can be expensive. 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->ComputeDatabaseMetrics(history_name); 6312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (thumbnail_db_) 6322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch thumbnail_db_->ComputeDatabaseMetrics(); 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 63546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.SetDatabases(db_.get(), thumbnail_db_.get()); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the long-running transaction. 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the first item in our database. 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start expiring old stuff. 64646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.StartExpiringOldStuff(TimeDelta::FromDays(kExpireDaysThreshold)); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 65046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) android_provider_backend_.reset( 65146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new AndroidProviderBackend(GetAndroidCacheFileName(), 65246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_.get(), 65346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thumbnail_db_.get(), 65446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_, 65546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delegate_.get())); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HISTOGRAM_TIMES("History.InitTime", 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HistoryBackend::OnMemoryPressure( 664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool trim_aggressively = memory_pressure_level == 666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (db_) 668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_->TrimMemory(trim_aggressively); 669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (thumbnail_db_) 670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch thumbnail_db_->TrimMemory(trim_aggressively); 671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloseAllDatabases() { 674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit the long-running transaction. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 67858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Forget the first recorded time since the database is closed. 67958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) first_recorded_time_ = base::Time(); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 681b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time time, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID referring_visit, 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top-level frame navigations are visible, everything else is hidden 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool new_hidden = !content::PageTransitionIsMainFrame(transition); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This code must stay in sync with 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExpireHistoryBackend::ExpireURLsForVisits(). 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typed, which would eliminate the need for this code. 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int typed_increment = 0; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type = 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((transition_type == content::PAGE_TRANSITION_TYPED && 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !content::PageTransitionIsRedirect(transition)) || 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typed_increment = 1; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only count the page visit if it came from user browsing and only count it 710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // once when cycling through a redirect chain. 711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_source == SOURCE_BROWSED && 712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) { 713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordTopPageVisitStats(url); 714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if this URL is already in the DB. 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update of an existing row. 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionStripQualifier(transition) != 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_RELOAD) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(url_info.visit_count() + 1); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typed_increment) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(url_info.typed_count() + typed_increment); 727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_info.last_visit() < time) 728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_info.set_last_visit(time); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow un-hiding of pages, never hiding. 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_hidden) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(url_id, url_info); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Addition of a new row. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(1); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(typed_increment); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(time); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(new_hidden); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = db_->AddURL(url_info); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding URL failed."; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(0, 0); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.id_ = url_id; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the visit with the time to the database. 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification of the visit. 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id) { 760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 761b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlVisited(transition, &url_info); 762b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLVisitedDetails> details(new URLVisitedDetails); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->transition = transition; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->row = url_info; 766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) details->visit_time = time; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetMostRecentRedirectsTo(url, &details->redirects); 770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, 771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 782b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // As of M37, we no longer maintain an archived database, ignore old visits. 79046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) 79146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 79446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLID url_id = db_->GetRowForURL(i->url(), &existing_url); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 79746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_id = db_->AddURL(*i); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) modified->changed_urls.push_back(*i); 804f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0. 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 81546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!db_->AddVisit(&visit_info, visit_source)) { 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (typed_url_syncable_service_.get()) 827b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 828b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modified.PassAs<HistoryDetails>()); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 84146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return time < expirer_.GetCurrentExpirationTime(); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 846b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 882b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 883b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 892b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_info.set_title(base::UTF8ToUTF16(url.spec())); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 918b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 933b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 939b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 947b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 953b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->UpdateURLRow(id, url); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 961b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 976b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 986b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 994b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 999f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)HistoryBackend::QueryURLResult HistoryBackend::QueryURL(const GURL& url, 1000f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool want_visits) { 1001f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QueryURLResult result; 1002f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result.success = db_ && db_->GetRowForURL(url, &result.row); 1003f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Optionally query the visits. 1004f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result.success && want_visits) 1005f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) db_->GetVisitsForURL(result.row.id(), &result.visits); 1006f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1009b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1010b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1011b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment usage --------------------------------------------------------------- 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteOldSegmentData() { 1016b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteSegmentData(Time::Now() - 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kSegmentDataRetention)); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QuerySegmentUsage( 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time from_time, 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_result_count) { 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1028b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the first time we query segments, invoke 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteOldSegmentData asynchronously. We do this to cleanup old 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries. 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!segment_queried_) { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_ = true; 103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HistoryBackend::DeleteOldSegmentData, this)); 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& term) { 1049b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 10530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLRow row; 10540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!db_->GetRowForURL(url, &row)) { 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->SetKeywordSearchTermsForURL(row.id(), keyword_id, term); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 10630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, 1064a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails>( 10650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new KeywordSearchUpdatedDetails(row, keyword_id, term))); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllSearchTermsForKeyword( 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id) { 1071b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetMostRecentKeywordSearchTerms( 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 1081a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& prefix, 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_count) { 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1086b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(request->value)); 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HistoryBackend::DeleteKeywordSearchTermForURL(const GURL& url) { 10940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!db_) 10950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 10960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 10970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 10980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!url_id) 10990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) db_->DeleteKeywordSearchTermForURL(url_id); 11010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BroadcastNotifications( 11030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, 11040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<HistoryDetails>(new KeywordSearchDeletedDetails(url_id))); 11050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleCommit(); 11060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 11070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HistoryBackend::DeleteMatchingURLsForKeyword(TemplateURLID keyword_id, 11095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& term) { 11105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_) 11115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 11125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<KeywordSearchTermRow> rows; 11145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_->GetKeywordSearchTermRows(term, &rows)) { 11155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<GURL> items_to_delete; 11165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLRow row; 11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<KeywordSearchTermRow>::iterator it = rows.begin(); 11185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != rows.end(); ++it) { 11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((it->keyword_id == keyword_id) && db_->GetURLRow(it->url_id, &row)) 11205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) items_to_delete.push_back(row.url()); 11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteURLs(items_to_delete); 11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)uint32 HistoryBackend::GetNextDownloadId() { 1129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return db_ ? db_->GetNextDownloadId() : content::DownloadItem::kInvalidId; 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HistoryBackend::CreateDownload(const history::DownloadRow& history_info) { 1147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 1148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool success = db_->CreateDownload(history_info); 11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 1151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return success; 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 11582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 11617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 11627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 11677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 11687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 11707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 11717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 11727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 11737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 11747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 11757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 11767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 11777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 11787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 11797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 11827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 11837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 11847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 11857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 1189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options) { 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 119946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QueryHistoryBasic(options, &request->value); 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 120246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QueryHistoryText(text_query, options, &request->value); 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 121346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HistoryBackend::QueryHistoryBasic(const QueryOptions& options, 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 121746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool has_more_results = db_->GetVisibleVisitsInRange(options, &visits); 12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 122646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!db_->GetURLRow(visit.url_id, &url_result)) { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 125646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HistoryBackend::QueryHistoryText(const base::string16& text_query, 1257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 126046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_->GetTextMatches(text_query, &text_matches); 1261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 126746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_->GetVisibleVisitsForURL(text_match.id(), options, &visits); 1268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Frontend to GetMostRecentRedirectsFrom from the history thread. 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsFrom( 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsFrom(url, &request->value); 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsTo( 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsTo(url, &request->value); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetVisibleVisitCountToHostRequest> request, 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time first_visit; 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = db_.get() && 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisibleVisitCountToHost(url, &count, &first_visit); 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, count, first_visit); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryTopURLsAndRedirects( 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count) { 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), false, NULL, NULL); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL>* top_urls = &request->value.a; 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectMap* redirects = &request->value.b; 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_urls->push_back(data[i]->GetURL()); 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*redirects)[top_urls->back()] = list; 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), true, top_urls, redirects); 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will replace QueryTopURLsAndRedirectsRequest. 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLs( 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryMostVisitedURLsRequest> request, 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back) { 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), MostVisitedURLList()); 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result = &request->value; 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryMostVisitedURLsImpl(result_count, days_back, result); 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), *result); 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryFilteredURLs( 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryFilteredURLsRequest> request, 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::VisitFilter& filter, 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool extended_info) { 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), FilteredURLList()); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURLList& result = request->value; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.push_back(url); 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), result); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back, 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result) { 1454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromDays(days_back), 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects; 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(url); 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsFrom( 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& from_url, 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID from_url_id = db_->GetRowForURL(from_url, NULL); 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(cur_visit, redirects); 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsTo( 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& to_url, 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID to_url_id = db_->GetRowForURL(to_url, NULL); 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsToSpecificVisit(cur_visit, redirects); 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryURLProviderParams* params) { 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExecuteWithDB should handle the NULL database case. 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->ExecuteWithDB(this, db_.get(), params); 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1549bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1550bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1551bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1552bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1553bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1554bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1555bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1556bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1557bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1558bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1559bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1560bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1561bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1562bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1563bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1564bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1565bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 15702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 1571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 15722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, 15732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 15742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryBackend::GetLargestFaviconForURL( 15780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& page_url, 15790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<int>& icon_types, 15800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int minimum_size_in_pixels, 1581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult* favicon_bitmap_result) { 15828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(favicon_bitmap_result); 15838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!db_ || !thumbnail_db_) 15858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 15888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 15908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings) || 15918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) icon_mappings.empty()) 15928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int required_icon_types = 0; 15958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator i = icon_types.begin(); 15968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_types.end(); ++i) { 15978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) required_icon_types |= *i; 15988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find the largest bitmap for each IconType placing in 16018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // |largest_favicon_bitmaps|. 16020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::map<favicon_base::IconType, FaviconBitmap> largest_favicon_bitmaps; 16038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<IconMapping>::const_iterator i = icon_mappings.begin(); 16048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_mappings.end(); ++i) { 16058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!(i->icon_type & required_icon_types)) 16068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 16078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 16088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(i->icon_id, &bitmap_id_sizes); 16098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap& largest = largest_favicon_bitmaps[i->icon_type]; 16108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<FaviconBitmapIDSize>::const_iterator j = 16118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_id_sizes.begin(); j != bitmap_id_sizes.end(); ++j) { 16128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest.bitmap_id == 0 || 16138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest.pixel_size.width() < j->pixel_size.width() && 16148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size.height() < j->pixel_size.height())) { 16158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.icon_id = i->icon_id; 16168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.bitmap_id = j->bitmap_id; 16178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size = j->pixel_size; 16188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_favicon_bitmaps.empty()) 16228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find an icon which is larger than minimum_size_in_pixels in the order of 16258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // icon_types. 16268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap largest_icon; 16278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator t = icon_types.begin(); 16288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) t != icon_types.end(); ++t) { 16290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::map<favicon_base::IconType, FaviconBitmap>::const_iterator f = 16300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest_favicon_bitmaps.begin(); 16310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f != largest_favicon_bitmaps.end(); 16320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++f) { 16338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (f->first & *t && 16348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.bitmap_id == 0 || 16358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.pixel_size.height() < f->second.pixel_size.height() && 16368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.width() < f->second.pixel_size.width()))) { 16378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon = f->second; 16388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_icon.pixel_size.width() > minimum_size_in_pixels && 16418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.height() > minimum_size_in_pixels) 16428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 16438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL icon_url; 16460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 16478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(largest_icon.icon_id, &icon_url, 16488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &icon_type)) { 16498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::Time last_updated; 1653f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult bitmap_result; 16548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_url = icon_url; 16558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_type = icon_type; 16568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(largest_icon.bitmap_id, 16578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &last_updated, 16588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.bitmap_data, 16598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.pixel_size)) { 16608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 16618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 16628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 16648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 16658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (bitmap_result.is_valid()) 16668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *favicon_bitmap_result = bitmap_result; 16678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) HISTOGRAM_TIMES("History.GetLargestFaviconForURL", 16698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks::Now() - beginning_time); 16708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 16718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 16762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 1677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 16782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, 16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 16840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id, 16852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 16862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScaleFactor desired_scale_factor, 1687f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 16880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ui::ScaleFactor> desired_scale_factors; 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors.push_back(desired_scale_factor); 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 16942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 16952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, 16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, 16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 1706f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 17072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 17082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 17092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 17150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1718b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 172290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 17382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 17442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 17452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 17522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 17532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 17552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 17582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 17702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 17742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 17752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 177658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Initial State: www.google.com/favicon.ico 16x16, 32x32 17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 17832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 17842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 17852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 179658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Difficulty 1: All but news.google.com/news_specific.ico are unmapped from 17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 18072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 18420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 18550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 1856f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapData>& 1857f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_bitmap_data) { 1858b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1863f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Build map of FaviconRawBitmapData for each icon url. 1864f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) typedef std::map<GURL, std::vector<favicon_base::FaviconRawBitmapData> > 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> icon_ids; 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 18800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id = 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 1886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1911b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 1925b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 1938b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 19470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 19480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch thumbnail_db_->GetFaviconIDForFaviconURL( 19490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_usage[i].favicon_url, favicon_base::FAVICON, NULL); 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 19550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON, 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 196246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client = GetHistoryClient(); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 197246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client && history_client->IsBookmarked(*url)) { 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 198390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 19840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *url, favicon_base::FAVICON, NULL)) { 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 1996a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details( 1997a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new FaviconChangedDetails); 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2000a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 2010f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 20130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!page_url || icon_types == favicon_base::FAVICON || 20140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_ICON || 20150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_PRECOMPOSED_ICON || 20160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == 20170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON)); 20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2020b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 20280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType selected_icon_type = favicon_base::INVALID_ICON; 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 20320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type_out; 20330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconID favicon_id = 203490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 203590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, 20612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 20650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id, 2066f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapData>& favicon_bitmap_data, 20672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 20682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 20702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2074f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapData> to_add = favicon_bitmap_data; 20752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 20772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 2078f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapData>::iterator match_it = 20790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.end(); 2080f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (std::vector<favicon_base::FaviconRawBitmapData>::iterator it = 20810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.begin(); 20820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != to_add.end(); 20830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 20842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 20852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 20932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 20982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 21022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 21032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 21042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 21052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 21142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 21152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool HistoryBackend::ValidateSetFaviconsParams(const std::vector< 2123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapData>& favicon_bitmap_data) const { 21242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 21252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 21312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 21322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 21332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 21342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 21352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 21382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 21412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 21422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 21492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 21502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 21522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 21552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 21562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 21572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 21582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 21592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 2167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results) { 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 21692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 21810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 21862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, favicon_bitmap_results); 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 21940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& candidate_favicon_ids, 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 2197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results) { 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 22070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID best_favicon_id = 0; 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors, 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_size_in_dip, 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Construct FaviconRawBitmapResults from |best_favicon_id| and 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 22420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 2250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult bitmap_result; 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 22710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 2272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 22930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> unmapped_icon_ids = icon_ids; 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 23140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID>::iterator icon_id_it = std::find( 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((icon_type == favicon_base::TOUCH_ICON && 23240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON) || 23250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON && 23260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_ICON) || 23270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == m->icon_type)) { 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details(new FaviconChangedDetails); 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 240490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.front()->Release(); 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_task_requests_.empty()) 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDBTaskRequest* request = db_task_requests_.front(); 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->value->RunOnDBThread(this, db_.get())) { 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task is done. Notify the callback. 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(); 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We AddRef'd the request before adding, need to release it now. 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Release(); 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tasks wants to run some more. Schedule it at the end of current tasks. 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request); 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And process it after an invoke later. 244490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ReleaseDBTasks() { 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::list<HistoryDBTaskRequest*>::iterator i = 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.clear(); 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 248558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!db_) 248658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 248858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 248958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) restrict_urls.empty()) { 249058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 249158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // possibility of an information leak. 249258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DeleteAllHistory(); 249358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 249458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Clearing parts of history, have the expirer do the depend 249558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 249658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 249758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 249858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // we want to get it on disk ASAP. 249958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Commit(); 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 25072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 25082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 25102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 25142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 25162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 25172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 25182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 252446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QueryHistoryBasic(options, &results); 25252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 25272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 25282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 25292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 25302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 25312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 25332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 25362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 25372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 25382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 25392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 25402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 25432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 25442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 25452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 25462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 25472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 25482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 25492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 25512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 25522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 25532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 25542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 25562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 25572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 25582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 25652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 25672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 25682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 25712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 25722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 25742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 25762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 25772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 25997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 26007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 26017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 26027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 26037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 26047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 26057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 26067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 26077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 26087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 26097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 26107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 26127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 262946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.SetDatabases(NULL, NULL); 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryDBTaskRequest> request) { 2638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(request.get()); 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_scheduled = !db_task_requests_.empty(); 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we up the refcount of the request. ProcessDBTaskImpl will 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release when done with the task. 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AddRef(); 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request.get()); 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!task_scheduled) { 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other tasks are scheduled. Process request now. 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 2655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails> details) { 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2658b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 2659a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->BroadcastNotifications(type, details.Pass()); 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid HistoryBackend::NotifySyncURLsModified(URLRows* rows) { 26630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) 26640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified(rows); 26650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 26660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2667b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 266846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool expired, 2669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 267146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, expired, rows); 2672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 269046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<URLAndTitle> starred_urls; 269146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client = GetHistoryClient(); 269246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client) 269346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client->GetBookmarks(&starred_urls); 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 27103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!ClearAllThumbnailHistory(kept_urls)) { 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 271658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 271758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Therefore, we clear the list afterwards to make sure nobody uses this 271858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // invalid data. 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Send out the notification that history is cleared. The in-memory database 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 2727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2729b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 2730a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2731a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(const URLRows& kept_urls) { 2735b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 27403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sql::Connection::Delete(GetFaviconsFileName()); 27413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 27423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Older version of the database. 2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Urls to retain mappings for. 27483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<GURL> urls_to_keep; 27493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); 27503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) i != kept_urls.end(); ++i) { 27513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) urls_to_keep.push_back(i->url()); 27523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Isolate from any long-running transaction. 27553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 27563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): If this fails, perhaps the database should be razed 27593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or deleted. 27603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!thumbnail_db_->RetainDataForPageUrls(urls_to_keep)) { 27613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->RollbackTransaction(); 27623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 278758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Insert the URLs into the temporary table. 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 279058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) db_->AddTemporaryURL(*i); 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 281146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)HistoryClient* HistoryBackend::GetHistoryClient() { 281246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client_) 281346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_->BlockUntilBookmarksLoaded(); 281446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return history_client_; 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2824b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention, 2832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &most_visited_urls); 2833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 2853