summaryrefslogtreecommitdiff
path: root/chromium/components/history
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/components/history
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
downloadqtwebengine-chromium-daa093eea7c773db06799a13bd7e4e2e2a9f8f14.tar.gz
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/history')
-rw-r--r--chromium/components/history/content/browser/web_contents_top_sites_observer.cc10
-rw-r--r--chromium/components/history/core/browser/BUILD.gn2
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.cc6
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.h7
-rw-r--r--chromium/components/history/core/browser/expire_history_backend_unittest.cc33
-rw-r--r--chromium/components/history/core/browser/history_backend.cc87
-rw-r--r--chromium/components/history/core/browser/history_backend.h16
-rw-r--r--chromium/components/history/core/browser/history_backend_unittest.cc196
-rw-r--r--chromium/components/history/core/browser/history_database.cc35
-rw-r--r--chromium/components/history/core/browser/history_service.cc18
-rw-r--r--chromium/components/history/core/browser/history_service.h14
-rw-r--r--chromium/components/history/core/browser/history_types.h1
-rw-r--r--chromium/components/history/core/browser/thumbnail_database.cc13
-rw-r--r--chromium/components/history/core/browser/thumbnail_database.h2
-rw-r--r--chromium/components/history/core/browser/thumbnail_database_unittest.cc13
-rw-r--r--chromium/components/history/core/browser/top_sites_backend.cc9
-rw-r--r--chromium/components/history/core/browser/top_sites_database.cc249
-rw-r--r--chromium/components/history/core/browser/top_sites_database.h42
-rw-r--r--chromium/components/history/core/browser/top_sites_database_unittest.cc68
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.cc105
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.h37
-rw-r--r--chromium/components/history/core/browser/top_sites_impl_unittest.cc393
-rw-r--r--chromium/components/history/core/browser/typed_url_data_type_controller.cc2
-rw-r--r--chromium/components/history/core/browser/typed_url_data_type_controller.h2
-rw-r--r--chromium/components/history/core/browser/typed_url_model_type_controller.cc108
-rw-r--r--chromium/components/history/core/browser/typed_url_model_type_controller.h47
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge.cc49
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge.h4
-rw-r--r--chromium/components/history/core/browser/typed_url_syncable_service.cc2
-rw-r--r--chromium/components/history/core/browser/typed_url_syncable_service.h2
-rw-r--r--chromium/components/history/core/browser/url_database.cc43
-rw-r--r--chromium/components/history/core/browser/url_database.h13
-rw-r--r--chromium/components/history/core/browser/url_database_unittest.cc9
-rw-r--r--chromium/components/history/core/browser/url_row.h2
-rw-r--r--chromium/components/history/core/browser/visit_database.cc42
-rw-r--r--chromium/components/history/core/browser/visit_database.h7
-rw-r--r--chromium/components/history/core/browser/visit_database_unittest.cc12
37 files changed, 1064 insertions, 636 deletions
diff --git a/chromium/components/history/content/browser/web_contents_top_sites_observer.cc b/chromium/components/history/content/browser/web_contents_top_sites_observer.cc
index 2e7f10bc91c..50546ecf828 100644
--- a/chromium/components/history/content/browser/web_contents_top_sites_observer.cc
+++ b/chromium/components/history/content/browser/web_contents_top_sites_observer.cc
@@ -38,8 +38,16 @@ WebContentsTopSitesObserver::~WebContentsTopSitesObserver() {
void WebContentsTopSitesObserver::NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) {
DCHECK(load_details.entry);
- if (top_sites_)
+
+ // Frame-wise, we only care about navigating the main frame.
+ // Type-wise, we only care about navigating to a new page, or renavigating to
+ // an existing navigation entry.
+ if (top_sites_ && load_details.is_main_frame &&
+ (load_details.type == content::NavigationType::NAVIGATION_TYPE_NEW_PAGE ||
+ load_details.type ==
+ content::NavigationType::NAVIGATION_TYPE_EXISTING_PAGE)) {
top_sites_->OnNavigationCommitted(load_details.entry->GetURL());
+ }
}
} // namespace history
diff --git a/chromium/components/history/core/browser/BUILD.gn b/chromium/components/history/core/browser/BUILD.gn
index f9c88c8c106..3e4bfbc7fb3 100644
--- a/chromium/components/history/core/browser/BUILD.gn
+++ b/chromium/components/history/core/browser/BUILD.gn
@@ -67,6 +67,8 @@ static_library("browser") {
"top_sites_observer.h",
"typed_url_data_type_controller.cc",
"typed_url_data_type_controller.h",
+ "typed_url_model_type_controller.cc",
+ "typed_url_model_type_controller.h",
"typed_url_sync_bridge.cc",
"typed_url_sync_bridge.h",
"typed_url_sync_metadata_database.cc",
diff --git a/chromium/components/history/core/browser/expire_history_backend.cc b/chromium/components/history/core/browser/expire_history_backend.cc
index 2e69c9286c2..b19fef9e160 100644
--- a/chromium/components/history/core/browser/expire_history_backend.cc
+++ b/chromium/components/history/core/browser/expire_history_backend.cc
@@ -135,6 +135,8 @@ namespace internal {
const base::Feature kClearOldOnDemandFavicons{
"ClearOldOnDemandFavicons", base::FEATURE_DISABLED_BY_DEFAULT};
+const int kOnDemandFaviconIsOldAfterDays = 30;
+
} // namespace internal
// ExpireHistoryBackend::DeleteEffects ----------------------------------------
@@ -499,7 +501,9 @@ void ExpireHistoryBackend::DoExpireIteration() {
work_queue_.push(reader);
} else {
// Otherwise do a final clean-up - remove old favicons not bound to visits.
- ClearOldOnDemandFavicons(GetCurrentExpirationTime());
+ ClearOldOnDemandFavicons(
+ base::Time::Now() -
+ base::TimeDelta::FromDays(internal::kOnDemandFaviconIsOldAfterDays));
}
ScheduleExpire();
diff --git a/chromium/components/history/core/browser/expire_history_backend.h b/chromium/components/history/core/browser/expire_history_backend.h
index f47666e4dd6..d571e8cfdec 100644
--- a/chromium/components/history/core/browser/expire_history_backend.h
+++ b/chromium/components/history/core/browser/expire_history_backend.h
@@ -6,10 +6,10 @@
#define COMPONENTS_HISTORY_CORE_BROWSER_EXPIRE_HISTORY_BACKEND_H_
#include <memory>
-#include <queue>
#include <set>
#include <vector>
+#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -46,6 +46,9 @@ typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders;
namespace internal {
// Feature that enables clearing old on-demand favicons.
extern const base::Feature kClearOldOnDemandFavicons;
+
+// The minimum number of days since last use for an icon to be considered old.
+extern const int kOnDemandFaviconIsOldAfterDays;
} // namespace internal
// Helper component to HistoryBackend that manages expiration and deleting of
@@ -269,7 +272,7 @@ class ExpireHistoryBackend {
// Work queue for periodic expiration tasks, used by DoExpireIteration() to
// determine what to do at an iteration, as well as populate it for future
// iterations.
- std::queue<const ExpiringVisitsReader*> work_queue_;
+ base::queue<const ExpiringVisitsReader*> work_queue_;
// Readers for various types of visits.
// TODO(dglazkov): If you are adding another one, please consider reorganizing
diff --git a/chromium/components/history/core/browser/expire_history_backend_unittest.cc b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
index be6bc13ac33..cdc1a82ec4d 100644
--- a/chromium/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
@@ -49,6 +49,12 @@ namespace {
bool MockCanAddURLToHistory(const GURL& url) {
return url.is_valid();
}
+
+base::Time GetOldFaviconThreshold() {
+ return base::Time::Now() -
+ base::TimeDelta::FromDays(internal::kOnDemandFaviconIsOldAfterDays);
+}
+
} // namespace
// ExpireHistoryTest -----------------------------------------------------------
@@ -908,13 +914,12 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteUnstarred) {
GURL url("http://google.com/favicon.ico");
favicon_base::FaviconID icon_id = thumb_db_->AddFavicon(
url, favicon_base::FAVICON, favicon, FaviconBitmapType::ON_DEMAND,
- base::Time::Now() - base::TimeDelta::FromDays(100), gfx::Size());
+ GetOldFaviconThreshold() - base::TimeDelta::FromSeconds(1), gfx::Size());
ASSERT_NE(0, icon_id);
GURL page_url("http://google.com/");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url, icon_id));
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(90));
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold());
// The icon gets deleted.
EXPECT_FALSE(thumb_db_->GetIconMappingsForPageURL(page_url, nullptr));
@@ -937,7 +942,7 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesNotDeleteStarred) {
GURL url("http://google.com/favicon.ico");
favicon_base::FaviconID icon_id = thumb_db_->AddFavicon(
url, favicon_base::FAVICON, favicon, FaviconBitmapType::ON_DEMAND,
- base::Time::Now() - base::TimeDelta::FromDays(100), gfx::Size());
+ GetOldFaviconThreshold() - base::TimeDelta::FromSeconds(1), gfx::Size());
ASSERT_NE(0, icon_id);
GURL page_url1("http://google.com/1");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url1, icon_id));
@@ -945,8 +950,7 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesNotDeleteStarred) {
GURL page_url2("http://google.com/2");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url2, icon_id));
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(90));
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold());
// Nothing gets deleted.
EXPECT_TRUE(thumb_db_->GetFaviconHeader(icon_id, nullptr, nullptr));
@@ -968,8 +972,8 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteAfterLongDelay) {
feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
// Previous clearing (2 days ago).
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(92));
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold() -
+ base::TimeDelta::FromDays(2));
// The blob does not encode any real bitmap, obviously.
const unsigned char kBlob[] = "0";
@@ -980,13 +984,12 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteAfterLongDelay) {
GURL url("http://google.com/favicon.ico");
favicon_base::FaviconID icon_id = thumb_db_->AddFavicon(
url, favicon_base::FAVICON, favicon, FaviconBitmapType::ON_DEMAND,
- base::Time::Now() - base::TimeDelta::FromDays(100), gfx::Size());
+ GetOldFaviconThreshold() - base::TimeDelta::FromSeconds(1), gfx::Size());
ASSERT_NE(0, icon_id);
GURL page_url("http://google.com/");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url, icon_id));
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(90));
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold());
// The icon gets deleted.
EXPECT_FALSE(thumb_db_->GetIconMappingsForPageURL(page_url, nullptr));
@@ -1002,8 +1005,7 @@ TEST_F(ExpireHistoryTest,
feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
// Previous clearing (5 minutes ago).
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(90) -
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold() -
base::TimeDelta::FromMinutes(5));
// The blob does not encode any real bitmap, obviously.
@@ -1015,15 +1017,14 @@ TEST_F(ExpireHistoryTest,
GURL url("http://google.com/favicon.ico");
favicon_base::FaviconID icon_id = thumb_db_->AddFavicon(
url, favicon_base::FAVICON, favicon, FaviconBitmapType::ON_DEMAND,
- base::Time::Now() - base::TimeDelta::FromDays(100), gfx::Size());
+ GetOldFaviconThreshold() - base::TimeDelta::FromSeconds(1), gfx::Size());
ASSERT_NE(0, icon_id);
GURL page_url1("http://google.com/1");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url1, icon_id));
GURL page_url2("http://google.com/2");
ASSERT_NE(0, thumb_db_->AddIconMapping(page_url2, icon_id));
- expirer_.ClearOldOnDemandFavicons(base::Time::Now() -
- base::TimeDelta::FromDays(90));
+ expirer_.ClearOldOnDemandFavicons(GetOldFaviconThreshold());
// Nothing gets deleted.
EXPECT_TRUE(thumb_db_->GetFaviconHeader(icon_id, nullptr, nullptr));
diff --git a/chromium/components/history/core/browser/history_backend.cc b/chromium/components/history/core/browser/history_backend.cc
index dec7e10fc08..6002fa2c56a 100644
--- a/chromium/components/history/core/browser/history_backend.cc
+++ b/chromium/components/history/core/browser/history_backend.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <functional>
+#include <limits>
#include <list>
#include <map>
#include <memory>
@@ -15,8 +16,6 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/feature_list.h"
#include "base/files/file_enumerator.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -55,7 +54,6 @@
#include "base/ios/scoped_critical_action.h"
#endif
-using base::debug::DumpWithoutCrashing;
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
@@ -74,6 +72,11 @@ using syncer::ModelTypeChangeProcessor;
namespace history {
+// TODO(crbug.com/746268): Clean up this toggle after impact is measured via
+// Finch, which is expected to be neutral.
+const base::Feature kAvoidStrippingRefFromFaviconPageUrls{
+ "AvoidStrippingRefFromFaviconPageUrls", base::FEATURE_DISABLED_BY_DEFAULT};
+
namespace {
void RunUnlessCanceled(
@@ -219,10 +222,8 @@ void HistoryBackend::Init(
if (base::FeatureList::IsEnabled(switches::kSyncUSSTypedURL)) {
typed_url_sync_bridge_ = base::MakeUnique<TypedURLSyncBridge>(
this, db_.get(),
- base::BindRepeating(
- &ModelTypeChangeProcessor::Create,
- // TODO(gangwu): use ReportUnrecoverableError before launch.
- base::BindRepeating(base::IgnoreResult(&DumpWithoutCrashing))));
+ base::BindRepeating(&ModelTypeChangeProcessor::Create,
+ base::RepeatingClosure()));
typed_url_sync_bridge_->Init();
} else {
typed_url_syncable_service_ =
@@ -976,9 +977,20 @@ void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url,
}
bool HistoryBackend::GetAllTypedURLs(URLRows* urls) {
- if (db_)
- return db_->GetAllTypedUrls(urls);
- return false;
+ DCHECK(urls);
+ if (!db_)
+ return false;
+ std::vector<URLID> url_ids;
+ if (!db_->GetAllURLIDsForTransition(ui::PAGE_TRANSITION_TYPED, &url_ids))
+ return false;
+ urls->reserve(url_ids.size());
+ for (const auto& url_id : url_ids) {
+ URLRow url;
+ if (!db_->GetURLRow(url_id, &url))
+ return false;
+ urls->push_back(url);
+ }
+ return true;
}
bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) {
@@ -1325,7 +1337,7 @@ void HistoryBackend::QueryHistoryText(const base::string16& text_query,
}
result->SetURLResults(std::move(matching_visits));
- if(!has_more_results && options.begin_time <= first_recorded_time_)
+ if (!has_more_results && options.begin_time <= first_recorded_time_)
result->set_reached_beginning(true);
}
@@ -1372,6 +1384,8 @@ void HistoryBackend::QueryMostVisitedURLs(int result_count,
if (!db_)
return;
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+
auto url_filter = backend_client_
? base::Bind(&HistoryBackendClient::IsWebSafe,
base::Unretained(backend_client_.get()))
@@ -1386,6 +1400,9 @@ void HistoryBackend::QueryMostVisitedURLs(int result_count,
MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects);
result->push_back(url);
}
+
+ UMA_HISTOGRAM_TIMES("History.QueryMostVisitedURLsTime",
+ base::TimeTicks::Now() - begin_time);
}
void HistoryBackend::GetRedirectsFromSpecificVisit(VisitID cur_visit,
@@ -1453,7 +1470,7 @@ void HistoryBackend::GetFavicon(
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) {
- UpdateFaviconMappingsAndFetchImpl(std::set<GURL>(), icon_url, icon_type,
+ UpdateFaviconMappingsAndFetchImpl(base::flat_set<GURL>(), icon_url, icon_type,
desired_sizes, bitmap_results);
}
@@ -1533,18 +1550,19 @@ void HistoryBackend::GetLargestFaviconForURL(
}
base::Time last_updated;
+ base::Time last_requested;
favicon_base::FaviconRawBitmapResult bitmap_result;
bitmap_result.icon_url = icon_url;
bitmap_result.icon_type = icon_type;
- if (!thumbnail_db_->GetFaviconBitmap(largest_icon.bitmap_id,
- &last_updated, nullptr,
- &bitmap_result.bitmap_data,
- &bitmap_result.pixel_size)) {
+ if (!thumbnail_db_->GetFaviconBitmap(
+ largest_icon.bitmap_id, &last_updated, &last_requested,
+ &bitmap_result.bitmap_data, &bitmap_result.pixel_size)) {
return;
}
bitmap_result.expired =
(Time::Now() - last_updated) > TimeDelta::FromDays(kFaviconRefetchDays);
+ bitmap_result.fetched_because_of_page_visit = last_requested.is_null();
if (bitmap_result.is_valid())
*favicon_bitmap_result = bitmap_result;
@@ -1585,7 +1603,7 @@ void HistoryBackend::GetFaviconForID(
}
void HistoryBackend::UpdateFaviconMappingsAndFetch(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
@@ -1754,11 +1772,11 @@ void HistoryBackend::MergeFavicon(
ScheduleCommit();
}
-void HistoryBackend::SetFavicons(const GURL& page_url,
+void HistoryBackend::SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps) {
- SetFaviconsImpl(page_url, icon_type, icon_url, bitmaps,
+ SetFaviconsImpl(page_urls, icon_type, icon_url, bitmaps,
FaviconBitmapType::ON_VISIT);
}
@@ -1775,7 +1793,7 @@ bool HistoryBackend::SetOnDemandFavicons(const GURL& page_url,
return false;
}
- return SetFaviconsImpl(page_url, icon_type, icon_url, bitmaps,
+ return SetFaviconsImpl({page_url}, icon_type, icon_url, bitmaps,
FaviconBitmapType::ON_DEMAND);
}
@@ -1862,11 +1880,13 @@ void HistoryBackend::SetImportedFavicons(
}
}
-bool HistoryBackend::SetFaviconsImpl(const GURL& page_url,
+bool HistoryBackend::SetFaviconsImpl(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps,
FaviconBitmapType type) {
+ DCHECK(!page_urls.empty());
+
if (!thumbnail_db_ || !db_)
return false;
@@ -1887,12 +1907,14 @@ bool HistoryBackend::SetFaviconsImpl(const GURL& page_url,
}
std::vector<favicon_base::FaviconID> icon_ids(1u, icon_id);
- bool mapping_changed =
- SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids);
+ for (const GURL& page_url : page_urls) {
+ bool mapping_changed =
+ SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids);
- if (mapping_changed) {
- // Notify the UI that this function changed an icon mapping.
- SendFaviconChangedNotificationForPageAndRedirects(page_url);
+ if (mapping_changed) {
+ // Notify the UI that this function changed an icon mapping.
+ SendFaviconChangedNotificationForPageAndRedirects(page_url);
+ }
}
if (favicon_data_modified && !favicon_created) {
@@ -1906,7 +1928,7 @@ bool HistoryBackend::SetFaviconsImpl(const GURL& page_url,
}
void HistoryBackend::UpdateFaviconMappingsAndFetchImpl(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
@@ -2095,17 +2117,19 @@ bool HistoryBackend::GetFaviconBitmapResultsForBestMatch(
for (size_t i = 0; i < best_bitmap_ids.size(); ++i) {
base::Time last_updated;
+ base::Time last_requested;
favicon_base::FaviconRawBitmapResult bitmap_result;
bitmap_result.icon_url = icon_url;
bitmap_result.icon_type = icon_type;
- if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], &last_updated,
- nullptr, &bitmap_result.bitmap_data,
- &bitmap_result.pixel_size)) {
+ if (!thumbnail_db_->GetFaviconBitmap(
+ best_bitmap_ids[i], &last_updated, &last_requested,
+ &bitmap_result.bitmap_data, &bitmap_result.pixel_size)) {
return false;
}
bitmap_result.expired =
(Time::Now() - last_updated) > TimeDelta::FromDays(kFaviconRefetchDays);
+ bitmap_result.fetched_because_of_page_visit = last_requested.is_null();
if (bitmap_result.is_valid())
favicon_bitmap_results->push_back(bitmap_result);
}
@@ -2125,7 +2149,8 @@ bool HistoryBackend::SetFaviconMappingsForPageAndRedirects(
GetCachedRecentRedirects(page_url, &redirects);
bool mappings_changed = SetFaviconMappingsForPages(redirects, icon_type,
icon_ids);
- if (page_url.has_ref()) {
+ if (page_url.has_ref() &&
+ !base::FeatureList::IsEnabled(kAvoidStrippingRefFromFaviconPageUrls)) {
// Refs often gets added by Javascript, but the redirect chain is keyed to
// the URL without a ref.
// TODO(crbug.com/746268): This can cause orphan favicons, i.e. without a
diff --git a/chromium/components/history/core/browser/history_backend.h b/chromium/components/history/core/browser/history_backend.h
index 1a698364b8c..7dc0043d7c1 100644
--- a/chromium/components/history/core/browser/history_backend.h
+++ b/chromium/components/history/core/browser/history_backend.h
@@ -15,8 +15,10 @@
#include <vector>
#include "base/cancelable_callback.h"
+#include "base/containers/flat_set.h"
#include "base/containers/hash_tables.h"
#include "base/containers/mru_cache.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -65,6 +67,8 @@ static const size_t kMaxFaviconsPerPage = 8;
// the thumbnail database.
static const size_t kMaxFaviconBitmapsPerIconURL = 8;
+extern const base::Feature kAvoidStrippingRefFromFaviconPageUrls;
+
// Keeps track of a queued HistoryDBTask. This class lives solely on the
// DB thread.
class QueuedHistoryDBTask {
@@ -309,7 +313,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results);
void UpdateFaviconMappingsAndFetch(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
@@ -321,7 +325,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
scoped_refptr<base::RefCountedMemory> bitmap_data,
const gfx::Size& pixel_size);
- void SetFavicons(const GURL& page_url,
+ // |page_urls| must not be empty.
+ void SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps);
@@ -534,6 +539,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsReplaceBitmapData);
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
SetFaviconsSameFaviconURLForTwoPages);
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsWithTwoPageURLs);
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB);
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForPageInDB);
FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForIconInDB);
@@ -685,8 +691,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// If |bitmaps_are_expired| is true, the icon for |icon_url| will be modified
// only if it's not present in the database. In that case, it will be
// initially set as expired. Returns whether the new bitmaps were actually
- // written.
- bool SetFaviconsImpl(const GURL& page_url,
+ // written. |page_urls| must not be empty.
+ bool SetFaviconsImpl(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps,
@@ -697,7 +703,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// added to the database from each element in |page_urls| (and all redirects)
// to |icon_url|.
void UpdateFaviconMappingsAndFetchImpl(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
diff --git a/chromium/components/history/core/browser/history_backend_unittest.cc b/chromium/components/history/core/browser/history_backend_unittest.cc
index 79b79003ad1..dee14a1639e 100644
--- a/chromium/components/history/core/browser/history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_unittest.cc
@@ -30,6 +30,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -1758,19 +1759,19 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirects) {
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
// Add a favicon.
- backend_->SetFavicons(url1, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::FAVICON, icon_url1, bitmaps);
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url2, favicon_base::FAVICON));
// Add one touch_icon
- backend_->SetFavicons(url1, favicon_base::TOUCH_ICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::TOUCH_ICON, icon_url1, bitmaps);
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::TOUCH_ICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url2, favicon_base::TOUCH_ICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
// Add one TOUCH_PRECOMPOSED_ICON
- backend_->SetFavicons(
- url1, favicon_base::TOUCH_PRECOMPOSED_ICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::TOUCH_PRECOMPOSED_ICON, icon_url1,
+ bitmaps);
// The touch_icon was replaced.
EXPECT_EQ(0u, NumIconMappingsForPageURL(url1, favicon_base::TOUCH_ICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
@@ -1782,7 +1783,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirects) {
NumIconMappingsForPageURL(url2, favicon_base::TOUCH_PRECOMPOSED_ICON));
// Add a touch_icon.
- backend_->SetFavicons(url1, favicon_base::TOUCH_ICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::TOUCH_ICON, icon_url1, bitmaps);
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::TOUCH_ICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
// The TOUCH_PRECOMPOSED_ICON was replaced.
@@ -1791,7 +1792,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirects) {
NumIconMappingsForPageURL(url1, favicon_base::TOUCH_PRECOMPOSED_ICON));
// Add a web manifest_icon.
- backend_->SetFavicons(url1, favicon_base::WEB_MANIFEST_ICON, icon_url2,
+ backend_->SetFavicons({url1}, favicon_base::WEB_MANIFEST_ICON, icon_url2,
bitmaps);
EXPECT_EQ(1u,
NumIconMappingsForPageURL(url1, favicon_base::WEB_MANIFEST_ICON));
@@ -1804,7 +1805,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirects) {
url1, favicon_base::TOUCH_PRECOMPOSED_ICON));
// Add a different favicon.
- backend_->SetFavicons(url1, favicon_base::FAVICON, icon_url2, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::FAVICON, icon_url2, bitmaps);
EXPECT_EQ(1u,
NumIconMappingsForPageURL(url1, favicon_base::WEB_MANIFEST_ICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
@@ -1851,7 +1852,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirectsWithFragment) {
redirects.push_back(url2);
backend_->recent_redirects_.Put(url2, redirects);
- backend_->SetFavicons(url1, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::FAVICON, icon_url1, bitmaps);
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url2, favicon_base::FAVICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url3, favicon_base::FAVICON));
@@ -1864,12 +1865,29 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageAndRedirectsWithFragment) {
backend_->recent_redirects_.Clear();
backend_->recent_redirects_.Put(url1, redirects);
- backend_->SetFavicons(url1, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({url1}, favicon_base::FAVICON, icon_url1, bitmaps);
EXPECT_EQ(1u, NumIconMappingsForPageURL(url1, favicon_base::FAVICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url2, favicon_base::FAVICON));
EXPECT_EQ(1u, NumIconMappingsForPageURL(url3, favicon_base::FAVICON));
}
+TEST_F(HistoryBackendTest,
+ SetFaviconMappingsForPageAndRedirectsWithFragmentWithoutStripping) {
+ base::test::ScopedFeatureList override_features;
+ override_features.InitAndEnableFeature(kAvoidStrippingRefFromFaviconPageUrls);
+
+ const GURL url("http://www.google.com#abc");
+ const GURL url_without_ref("http://www.google.com");
+ const GURL icon_url("http://www.google.com/icon");
+ backend_->SetFavicons(
+ {url}, favicon_base::FAVICON, icon_url,
+ std::vector<SkBitmap>{CreateBitmap(SK_ColorBLUE, kSmallEdgeSize)});
+
+ EXPECT_EQ(1u, NumIconMappingsForPageURL(url, favicon_base::FAVICON));
+ EXPECT_EQ(0u,
+ NumIconMappingsForPageURL(url_without_ref, favicon_base::FAVICON));
+}
+
// Test that |recent_redirects_| stores the full redirect chain in case of
// client redirects. In this case, a server-side redirect is followed by a
// client-side one.
@@ -1905,7 +1923,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageDuplicates) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
- backend_->SetFavicons(url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({url}, favicon_base::FAVICON, icon_url, bitmaps);
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL(
@@ -1913,7 +1931,7 @@ TEST_F(HistoryBackendTest, SetFaviconMappingsForPageDuplicates) {
EXPECT_EQ(1u, icon_mappings.size());
IconMappingID mapping_id = icon_mappings[0].mapping_id;
- backend_->SetFavicons(url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({url}, favicon_base::FAVICON, icon_url, bitmaps);
icon_mappings.clear();
EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL(
@@ -1935,7 +1953,7 @@ TEST_F(HistoryBackendTest, SetFaviconsDeleteBitmaps) {
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
// Test initial state.
std::vector<IconMapping> icon_mappings;
@@ -1961,7 +1979,7 @@ TEST_F(HistoryBackendTest, SetFaviconsDeleteBitmaps) {
// the small bitmap is in fact deleted.
bitmaps.clear();
bitmaps.push_back(CreateBitmap(SK_ColorWHITE, kLargeEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
scoped_refptr<base::RefCountedMemory> bitmap_data_out;
gfx::Size pixel_size_out;
@@ -1987,7 +2005,7 @@ TEST_F(HistoryBackendTest, SetFaviconsReplaceBitmapData) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
// Add bitmap to the database.
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
favicon_base::FaviconID original_favicon_id =
backend_->thumbnail_db_->GetFaviconIDForFaviconURL(icon_url,
@@ -2002,7 +2020,7 @@ TEST_F(HistoryBackendTest, SetFaviconsReplaceBitmapData) {
// Call SetFavicons() with completely identical data.
bitmaps[0] = CreateBitmap(SK_ColorBLUE, kSmallEdgeSize);
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
favicon_base::FaviconID updated_favicon_id =
backend_->thumbnail_db_->GetFaviconIDForFaviconURL(icon_url,
@@ -2017,7 +2035,7 @@ TEST_F(HistoryBackendTest, SetFaviconsReplaceBitmapData) {
// Call SetFavicons() with a different bitmap of the same size.
bitmaps[0] = CreateBitmap(SK_ColorWHITE, kSmallEdgeSize);
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
updated_favicon_id = backend_->thumbnail_db_->GetFaviconIDForFaviconURL(
icon_url, favicon_base::FAVICON);
@@ -2045,12 +2063,12 @@ TEST_F(HistoryBackendTest, SetFaviconsSameFaviconURLForTwoPages) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url, bitmaps);
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{page_url2}, icon_url, favicon_base::FAVICON,
- GetEdgeSizesSmallAndLarge(), &bitmap_results);
+ {page_url2}, icon_url, favicon_base::FAVICON, GetEdgeSizesSmallAndLarge(),
+ &bitmap_results);
// Check that the same FaviconID is mapped to both page URLs.
std::vector<IconMapping> icon_mappings;
@@ -2069,8 +2087,8 @@ TEST_F(HistoryBackendTest, SetFaviconsSameFaviconURLForTwoPages) {
// Change the icon URL that |page_url1| is mapped to.
bitmaps.clear();
bitmaps.push_back(CreateBitmap(SK_ColorWHITE, kSmallEdgeSize));
- backend_->SetFavicons(
- page_url1, favicon_base::FAVICON, icon_url_new, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url_new,
+ bitmaps);
// |page_url1| should map to a new FaviconID and have valid bitmap data.
icon_mappings.clear();
@@ -2099,6 +2117,33 @@ TEST_F(HistoryBackendTest, SetFaviconsSameFaviconURLForTwoPages) {
EXPECT_EQ(2u, favicon_bitmaps.size());
}
+// Test that if two pages share the same favicon, reported via a single call to
+// SetFavicons(), it gets associated to both page URLs.
+TEST_F(HistoryBackendTest, SetFaviconsWithTwoPageURLs) {
+ GURL icon_url("http://www.google.com/favicon.ico");
+ GURL page_url1("http://www.google.com");
+ GURL page_url2("http://www.google.ca");
+ std::vector<SkBitmap> bitmaps;
+ bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
+ bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
+
+ backend_->SetFavicons({page_url1, page_url2}, favicon_base::FAVICON, icon_url,
+ bitmaps);
+
+ std::vector<IconMapping> icon_mappings;
+ EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL(
+ page_url1, &icon_mappings));
+ ASSERT_EQ(1u, icon_mappings.size());
+ favicon_base::FaviconID favicon_id = icon_mappings[0].icon_id;
+ EXPECT_NE(0, favicon_id);
+
+ icon_mappings.clear();
+ EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL(
+ page_url2, &icon_mappings));
+ ASSERT_EQ(1u, icon_mappings.size());
+ EXPECT_EQ(favicon_id, icon_mappings[0].icon_id);
+}
+
// Tests calling SetOnDemandFavicons(). Neither |page_url| nor |icon_url| are
// known to the database.
TEST_F(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB) {
@@ -2108,7 +2153,6 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB) {
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorRED, kSmallEdgeSize));
- // Call SetOnDemandFavicons() with a different icon URL and bitmap data.
EXPECT_TRUE(backend_->SetOnDemandFavicons(page_url, favicon_base::FAVICON,
icon_url, bitmaps));
@@ -2119,10 +2163,17 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB) {
FaviconBitmap favicon_bitmap;
ASSERT_TRUE(GetOnlyFaviconBitmap(favicon_id, &favicon_bitmap));
- // The original bitmap should have been retrieved.
+ // The newly set bitmap should have been retrieved.
EXPECT_TRUE(BitmapColorEqual(SK_ColorRED, favicon_bitmap.bitmap_data));
- // The favicon should not be marked as expired.
+ // The favicon should be marked as expired.
EXPECT_EQ(base::Time(), favicon_bitmap.last_updated);
+
+ // The raw bitmap result is marked as fetched on-demand.
+ favicon_base::FaviconRawBitmapResult result;
+ backend_->GetLargestFaviconForURL(page_url,
+ std::vector<int>{favicon_base::FAVICON},
+ kSmallEdgeSize, &result);
+ EXPECT_FALSE(result.fetched_because_of_page_visit);
}
// Tests calling SetOnDemandFavicons(). |page_url| is known to the database
@@ -2135,7 +2186,7 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForPageInDB) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
// Add bitmap to the database.
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url1, bitmaps);
favicon_base::FaviconID original_favicon_id =
backend_->thumbnail_db_->GetFaviconIDForFaviconURL(icon_url1,
favicon_base::FAVICON);
@@ -2154,6 +2205,13 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForPageInDB) {
EXPECT_TRUE(BitmapColorEqual(SK_ColorBLUE, favicon_bitmap.bitmap_data));
// The favicon should not be marked as expired.
EXPECT_NE(base::Time(), favicon_bitmap.last_updated);
+
+ // The raw bitmap result is not marked as fetched on-demand.
+ favicon_base::FaviconRawBitmapResult result;
+ backend_->GetLargestFaviconForURL(page_url,
+ std::vector<int>{favicon_base::FAVICON},
+ kSmallEdgeSize, &result);
+ EXPECT_TRUE(result.fetched_because_of_page_visit);
}
// Tests calling SetOnDemandFavicons(). |page_url| is not known to the
@@ -2166,7 +2224,8 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForIconInDB) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
// Add bitmap to the database.
- backend_->SetFavicons(old_page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({old_page_url}, favicon_base::FAVICON, icon_url,
+ bitmaps);
favicon_base::FaviconID original_favicon_id =
backend_->thumbnail_db_->GetFaviconIDForFaviconURL(icon_url,
favicon_base::FAVICON);
@@ -2187,6 +2246,13 @@ TEST_F(HistoryBackendTest, SetOnDemandFaviconsForIconInDB) {
EXPECT_TRUE(BitmapColorEqual(SK_ColorBLUE, favicon_bitmap.bitmap_data));
// The favicon should not be marked as expired.
EXPECT_NE(base::Time(), favicon_bitmap.last_updated);
+
+ // The raw bitmap result is not marked as fetched on-demand.
+ favicon_base::FaviconRawBitmapResult result;
+ backend_->GetLargestFaviconForURL(page_url,
+ std::vector<int>{favicon_base::FAVICON},
+ kSmallEdgeSize, &result);
+ EXPECT_TRUE(result.fetched_because_of_page_visit);
}
// Test repeatedly calling MergeFavicon(). |page_url| is initially not known
@@ -2244,7 +2310,7 @@ TEST_F(HistoryBackendTest, MergeFaviconPageURLInDB) {
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url1, bitmaps);
// Test initial state.
std::vector<IconMapping> icon_mappings;
@@ -2362,7 +2428,7 @@ TEST_F(HistoryBackendTest, MergeFaviconIconURLMappedToDifferentPageURL) {
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url, bitmaps);
// Test initial state.
std::vector<IconMapping> icon_mappings;
@@ -2481,7 +2547,7 @@ TEST_F(HistoryBackendTest, MergeFaviconShowsUpInGetFaviconsForURLResult) {
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
// Set some preexisting favicons for |page_url|.
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
// Merge small favicon.
std::vector<unsigned char> data;
@@ -2524,7 +2590,8 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationNewFavicon) {
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url1,
+ bitmaps);
ASSERT_EQ(1u, favicon_changed_notifications_page_urls().size());
EXPECT_EQ(page_url1, favicon_changed_notifications_page_urls()[0]);
EXPECT_EQ(0u, favicon_changed_notifications_icon_urls().size());
@@ -2557,7 +2624,7 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationBitmapDataChanged) {
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
ClearBroadcastedNotifications();
}
@@ -2565,7 +2632,7 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationBitmapDataChanged) {
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorWHITE, kSmallEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
EXPECT_EQ(0u, favicon_changed_notifications_page_urls().size());
ASSERT_EQ(1u, favicon_changed_notifications_icon_urls().size());
EXPECT_EQ(icon_url, favicon_changed_notifications_icon_urls()[0]);
@@ -2607,20 +2674,22 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationIconMappingChanged) {
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url1, bitmaps);
- backend_->SetFavicons(page_url2, favicon_base::FAVICON, icon_url2, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url1,
+ bitmaps);
+ backend_->SetFavicons({page_url2}, favicon_base::FAVICON, icon_url2,
+ bitmaps);
// Map |page_url3| to |icon_url1| so that the test does not delete the
// favicon at |icon_url1|.
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{page_url3}, icon_url1, favicon_base::FAVICON,
+ {page_url3}, icon_url1, favicon_base::FAVICON,
GetEdgeSizesSmallAndLarge(), &bitmap_results);
ClearBroadcastedNotifications();
}
// SetFavicons()
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url2, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url2, bitmaps);
EXPECT_THAT(favicon_changed_notifications_page_urls(),
ElementsAre(page_url1));
EXPECT_EQ(0u, favicon_changed_notifications_icon_urls().size());
@@ -2638,7 +2707,7 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationIconMappingChanged) {
{
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{page_url1}, icon_url2, favicon_base::FAVICON,
+ {page_url1}, icon_url2, favicon_base::FAVICON,
GetEdgeSizesSmallAndLarge(), &bitmap_results);
EXPECT_THAT(favicon_changed_notifications_page_urls(),
ElementsAre(page_url1));
@@ -2666,7 +2735,8 @@ TEST_F(HistoryBackendTest,
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url4, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url4}, favicon_base::FAVICON, icon_url,
+ bitmaps);
ClearBroadcastedNotifications();
}
@@ -2710,14 +2780,16 @@ TEST_F(HistoryBackendTest,
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url1, bitmaps);
- backend_->SetFavicons(page_url2, favicon_base::FAVICON, icon_url2, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url1,
+ bitmaps);
+ backend_->SetFavicons({page_url2}, favicon_base::FAVICON, icon_url2,
+ bitmaps);
// Map |page_url3| to |icon_url1| so that the test does not delete the
// favicon at |icon_url1|.
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{page_url3}, icon_url1, favicon_base::FAVICON,
+ {page_url3}, icon_url1, favicon_base::FAVICON,
GetEdgeSizesSmallAndLarge(), &bitmap_results);
ClearBroadcastedNotifications();
}
@@ -2726,7 +2798,8 @@ TEST_F(HistoryBackendTest,
{
std::vector<SkBitmap> bitmaps;
bitmaps.push_back(CreateBitmap(SK_ColorWHITE, kSmallEdgeSize));
- backend_->SetFavicons(page_url1, favicon_base::FAVICON, icon_url2, bitmaps);
+ backend_->SetFavicons({page_url1}, favicon_base::FAVICON, icon_url2,
+ bitmaps);
ASSERT_EQ(1u, favicon_changed_notifications_page_urls().size());
EXPECT_EQ(page_url1, favicon_changed_notifications_page_urls()[0]);
ASSERT_EQ(1u, favicon_changed_notifications_icon_urls().size());
@@ -2850,11 +2923,11 @@ TEST_F(HistoryBackendTest, NoFaviconChangedNotifications) {
ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_bytes));
// Setup
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
ClearBroadcastedNotifications();
// SetFavicons()
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
// MergeFavicon()
backend_->MergeFavicon(page_url, icon_url, favicon_base::FAVICON,
@@ -2864,7 +2937,7 @@ TEST_F(HistoryBackendTest, NoFaviconChangedNotifications) {
{
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{page_url}, icon_url, favicon_base::FAVICON,
+ {page_url}, icon_url, favicon_base::FAVICON,
GetEdgeSizesSmallAndLarge(), &bitmap_results);
}
@@ -2886,10 +2959,10 @@ TEST_F(HistoryBackendTest, TestGetFaviconsForURLWithIconTypesPriority) {
touch_bitmaps.push_back(CreateBitmap(SK_ColorWHITE, 64));
// Set some preexisting favicons for |page_url|.
- backend_->SetFavicons(
- page_url, favicon_base::FAVICON, icon_url, favicon_bitmaps);
- backend_->SetFavicons(
- page_url, favicon_base::TOUCH_ICON, touch_icon_url, touch_bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url,
+ favicon_bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::TOUCH_ICON, touch_icon_url,
+ touch_bitmaps);
favicon_base::FaviconRawBitmapResult result;
std::vector<int> icon_types;
@@ -2923,10 +2996,10 @@ TEST_F(HistoryBackendTest, TestGetFaviconsForURLReturnFavicon) {
touch_bitmaps.push_back(CreateBitmap(SK_ColorWHITE, 32));
// Set some preexisting favicons for |page_url|.
- backend_->SetFavicons(
- page_url, favicon_base::FAVICON, icon_url, favicon_bitmaps);
- backend_->SetFavicons(
- page_url, favicon_base::TOUCH_ICON, touch_icon_url, touch_bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url,
+ favicon_bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::TOUCH_ICON, touch_icon_url,
+ touch_bitmaps);
favicon_base::FaviconRawBitmapResult result;
std::vector<int> icon_types;
@@ -2956,7 +3029,7 @@ TEST_F(HistoryBackendTest, TestGetFaviconsForURLReturnFaviconEvenItSmaller) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, 16));
// Set preexisting favicons for |page_url|.
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
favicon_base::FaviconRawBitmapResult result;
std::vector<int> icon_types;
@@ -3011,7 +3084,7 @@ TEST_F(HistoryBackendTest, GetFaviconsFromDBSelectClosestMatch) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
bitmaps.push_back(CreateBitmap(SK_ColorRED, kLargeEdgeSize));
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url, bitmaps);
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results_out;
EXPECT_TRUE(backend_->GetFaviconsFromDB(page_url,
@@ -3053,8 +3126,9 @@ TEST_F(HistoryBackendTest, GetFaviconsFromDBIconType) {
bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize));
std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url1, bitmaps);
- backend_->SetFavicons(page_url, favicon_base::TOUCH_ICON, icon_url2, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url1, bitmaps);
+ backend_->SetFavicons({page_url}, favicon_base::TOUCH_ICON, icon_url2,
+ bitmaps);
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results_out;
EXPECT_TRUE(backend_->GetFaviconsFromDB(page_url,
@@ -3085,9 +3159,9 @@ TEST_F(HistoryBackendTest, GetFaviconsFromDBMultipleIconTypes) {
const GURL icon_url2("http://www.google.com/icon2.png");
std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
- backend_->SetFavicons(page_url, favicon_base::FAVICON, icon_url1,
+ backend_->SetFavicons({page_url}, favicon_base::FAVICON, icon_url1,
{CreateBitmap(SK_ColorBLUE, kSmallEdgeSize)});
- backend_->SetFavicons(page_url, favicon_base::TOUCH_ICON, icon_url2,
+ backend_->SetFavicons({page_url}, favicon_base::TOUCH_ICON, icon_url2,
{CreateBitmap(SK_ColorBLUE, kLargeEdgeSize)});
struct TestCase {
@@ -3142,8 +3216,8 @@ TEST_F(HistoryBackendTest, UpdateFaviconMappingsAndFetchNoDB) {
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
backend_->UpdateFaviconMappingsAndFetch(
- std::set<GURL>{GURL()}, GURL(), favicon_base::FAVICON,
- GetEdgeSizesSmallAndLarge(), &bitmap_results);
+ {GURL()}, GURL(), favicon_base::FAVICON, GetEdgeSizesSmallAndLarge(),
+ &bitmap_results);
EXPECT_TRUE(bitmap_results.empty());
}
diff --git a/chromium/components/history/core/browser/history_database.cc b/chromium/components/history/core/browser/history_database.cc
index 59dcff235b9..c3db915b635 100644
--- a/chromium/components/history/core/browser/history_database.cc
+++ b/chromium/components/history/core/browser/history_database.cc
@@ -37,7 +37,7 @@ namespace {
// Current version number. We write databases at the "current" version number,
// but any previous version that can read the "compatible" one can make do with
// our database without *too* many bad effects.
-const int kCurrentVersionNumber = 36;
+const int kCurrentVersionNumber = 37;
const int kCompatibleVersionNumber = 16;
const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
const int kMaxHostsInMemory = 10000;
@@ -563,23 +563,8 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
}
if (cur_version == 34) {
- /*
- This code is commented out because we suspect the additional disk storage
- requirements of duplicating the URL table to update the schema cause
- some devices to run out of storage. Errors during initialization are
- very disruptive to the user experience.
-
- TODO(https://crbug.com/736136) figure out how to update users to use
- AUTOINCREMENT.
-
- // AUTOINCREMENT is added to urls table PRIMARY KEY(id), need to recreate a
- // new table and copy all contents over. favicon_id is removed from urls
- // table since we never use it. Also typed_url_sync_metadata and
- // autofill_model_type_state tables are introduced, no migration needed for
- // those two tables.
- if (!RecreateURLTableWithAllContents())
- return LogMigrationFailure(34);
- */
+ // This originally contained an autoincrement migration which was abandoned
+ // and added back in version 36. (see https://crbug.com/736136)
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
@@ -591,6 +576,20 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
meta_table_.SetVersionNumber(cur_version);
}
+ if (cur_version == 36) {
+ // Version 34 added AUTOINCREMENT but was reverted. Since some users will
+ // have been migrated and others not, explicitly check for the AUTOINCREMENT
+ // annotation rather than the version number.
+ if (!URLTableContainsAutoincrement()) {
+ if (!RecreateURLTableWithAllContents())
+ return LogMigrationFailure(36);
+ }
+
+ DCHECK(URLTableContainsAutoincrement());
+ cur_version++;
+ meta_table_.SetVersionNumber(cur_version);
+ }
+
// ========================= ^^ new migration code goes here ^^
// ADDING NEW MIGRATION CODE
// =========================
diff --git a/chromium/components/history/core/browser/history_service.cc b/chromium/components/history/core/browser/history_service.cc
index 982a8b1f455..200e440b47e 100644
--- a/chromium/components/history/core/browser/history_service.cc
+++ b/chromium/components/history/core/browser/history_service.cc
@@ -574,7 +574,7 @@ base::CancelableTaskTracker::TaskId HistoryService::GetFaviconForID(
base::CancelableTaskTracker::TaskId
HistoryService::UpdateFaviconMappingsAndFetch(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
@@ -611,18 +611,26 @@ void HistoryService::MergeFavicon(
page_url, icon_url, icon_type, bitmap_data, pixel_size));
}
-void HistoryService::SetFavicons(const GURL& page_url,
+void HistoryService::SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps) {
DCHECK(backend_task_runner_) << "History service being called after cleanup";
DCHECK(thread_checker_.CalledOnValidThread());
- if (history_client_ && !history_client_->CanAddURL(page_url))
+
+ base::flat_set<GURL> page_urls_to_save;
+ page_urls_to_save.reserve(page_urls.capacity());
+ for (const GURL& page_url : page_urls) {
+ if (!history_client_ || history_client_->CanAddURL(page_url))
+ page_urls_to_save.insert(page_url);
+ }
+
+ if (page_urls_to_save.empty())
return;
ScheduleTask(PRIORITY_NORMAL,
base::Bind(&HistoryBackend::SetFavicons, history_backend_,
- page_url, icon_type, icon_url, bitmaps));
+ page_urls_to_save, icon_type, icon_url, bitmaps));
}
void HistoryService::SetOnDemandFavicons(const GURL& page_url,
@@ -981,7 +989,7 @@ syncer::SyncDataList HistoryService::GetAllSyncData(
}
syncer::SyncError HistoryService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
delete_directive_handler_.ProcessSyncChanges(this, change_list);
return syncer::SyncError();
diff --git a/chromium/components/history/core/browser/history_service.h b/chromium/components/history/core/browser/history_service.h
index 140bbd353af..9b79d259d4f 100644
--- a/chromium/components/history/core/browser/history_service.h
+++ b/chromium/components/history/core/browser/history_service.h
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_list.h"
+#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -535,7 +536,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
protected:
@@ -707,7 +708,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
// just mapped to |page_urls| are returned. If |desired_sizes| has a '0'
// entry, the largest favicon bitmap is returned.
base::CancelableTaskTracker::TaskId UpdateFaviconMappingsAndFetch(
- const std::set<GURL>& page_urls,
+ const base::flat_set<GURL>& page_urls,
const GURL& icon_url,
favicon_base::IconType icon_type,
const std::vector<int>& desired_sizes,
@@ -740,13 +741,14 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
scoped_refptr<base::RefCountedMemory> bitmap_data,
const gfx::Size& pixel_size);
- // Used by the FaviconService to replace all of the favicon bitmaps mapped to
- // |page_url| for |icon_type|.
+ // Used by the FaviconService to replace the favicon bitmaps mapped to all
+ // URLs in |page_urls| for |icon_type|.
// Use MergeFavicon() if |bitmaps| is incomplete, and favicon bitmaps in the
// database should be preserved if possible. For instance, favicon bitmaps
// from sync are 1x only. MergeFavicon() is used to avoid deleting the 2x
- // favicon bitmap if it is present in the history backend.
- void SetFavicons(const GURL& page_url,
+ // favicon bitmap if it is present in the history backend. |page_urls| must
+ // not be empty.
+ void SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps);
diff --git a/chromium/components/history/core/browser/history_types.h b/chromium/components/history/core/browser/history_types.h
index 00b6cb00aa8..fd6b86231a7 100644
--- a/chromium/components/history/core/browser/history_types.h
+++ b/chromium/components/history/core/browser/history_types.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <deque>
#include <map>
#include <set>
#include <string>
diff --git a/chromium/components/history/core/browser/thumbnail_database.cc b/chromium/components/history/core/browser/thumbnail_database.cc
index d452bd5d744..01933fc464c 100644
--- a/chromium/components/history/core/browser/thumbnail_database.cc
+++ b/chromium/components/history/core/browser/thumbnail_database.cc
@@ -414,21 +414,16 @@ void ThumbnailDatabase::TrimMemory(bool aggressively) {
std::map<favicon_base::FaviconID, IconMappingsForExpiry>
ThumbnailDatabase::GetOldOnDemandFavicons(base::Time threshold) {
- // Restrict to on-demand bitmaps (i.e. with last_requested != 0). This is
- // called rarely during history expiration cleanup and hence not worth
+ // Restrict to on-demand bitmaps (i.e. with last_requested != 0).
+ // This is called rarely during history expiration cleanup and hence not worth
// caching.
- // TODO(jkrcal): In M63, remove the "(last_requested=0 AND last_updated=0)"
- // clause which is only transitional - to clean up expired icons (previously,
- // on-demand favicons were stored as expired on-visit favicons).
sql::Statement old_icons(db_.GetUniqueStatement(
"SELECT favicons.id, favicons.url, icon_mapping.page_url "
"FROM favicons "
"JOIN favicon_bitmaps ON (favicon_bitmaps.icon_id = favicons.id) "
"JOIN icon_mapping ON (icon_mapping.icon_id = favicon_bitmaps.icon_id) "
- "WHERE ((favicon_bitmaps.last_requested = 0 AND "
- " favicon_bitmaps.last_updated = 0) OR "
- " (favicon_bitmaps.last_requested > 0 AND "
- " favicon_bitmaps.last_requested < ?))"));
+ "WHERE (favicon_bitmaps.last_requested > 0 AND "
+ " favicon_bitmaps.last_requested < ?)"));
old_icons.BindInt64(0, threshold.ToInternalValue());
std::map<favicon_base::FaviconID, IconMappingsForExpiry> icon_mappings;
diff --git a/chromium/components/history/core/browser/thumbnail_database.h b/chromium/components/history/core/browser/thumbnail_database.h
index f9ba1c71de4..bd29eb4938b 100644
--- a/chromium/components/history/core/browser/thumbnail_database.h
+++ b/chromium/components/history/core/browser/thumbnail_database.h
@@ -28,7 +28,7 @@ class HistoryBackendClient;
// The minimum number of days after which last_requested field gets updated.
// All earlier updates are ignored.
-static const int kFaviconUpdateLastRequestedAfterDays = 14;
+static const int kFaviconUpdateLastRequestedAfterDays = 10;
// This database interface is owned by the history backend and runs on the
// history thread. It is a totally separate component from history partially
diff --git a/chromium/components/history/core/browser/thumbnail_database_unittest.cc b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
index ffbf876080c..3bf1afb842b 100644
--- a/chromium/components/history/core/browser/thumbnail_database_unittest.cc
+++ b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
@@ -413,7 +413,7 @@ TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsReturnsOld) {
// if the on-visit icons have expired. We need this behavior in order to delete
// icons stored via HistoryService::SetOnDemandFavicons() prior to on-demand
// icons setting the "last_requested" time.
-TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsReturnsExpired) {
+TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsDoesNotReturnExpired) {
ThumbnailDatabase db(nullptr);
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
db.BeginTransaction();
@@ -432,14 +432,11 @@ TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsReturnsExpired) {
ASSERT_NE(0, db.AddIconMapping(page_url, icon));
ASSERT_TRUE(db.SetFaviconOutOfDate(icon));
- // The threshold is ignored for expired icons.
- auto map = db.GetOldOnDemandFavicons(/*threshold=*/base::Time::Now());
+ base::Time get_older_than = start + base::TimeDelta::FromSeconds(1);
+ auto map = db.GetOldOnDemandFavicons(get_older_than);
- // The icon is returned.
- EXPECT_THAT(map, ElementsAre(Pair(
- icon, AllOf(Field(&IconMappingsForExpiry::icon_url, url),
- Field(&IconMappingsForExpiry::page_urls,
- ElementsAre(page_url))))));
+ // No icon is returned.
+ EXPECT_TRUE(map.empty());
}
// Test that ThumbnailDatabase::GetOldOnDemandFavicons() does not return
diff --git a/chromium/components/history/core/browser/top_sites_backend.cc b/chromium/components/history/core/browser/top_sites_backend.cc
index aa107e9fc85..a35248e43ff 100644
--- a/chromium/components/history/core/browser/top_sites_backend.cc
+++ b/chromium/components/history/core/browser/top_sites_backend.cc
@@ -118,14 +118,7 @@ void TopSitesBackend::UpdateTopSitesOnDBThread(
base::TimeTicks begin_time = base::TimeTicks::Now();
- for (size_t i = 0; i < delta.deleted.size(); ++i)
- db_->RemoveURL(delta.deleted[i]);
-
- for (size_t i = 0; i < delta.added.size(); ++i)
- db_->SetPageThumbnail(delta.added[i].url, delta.added[i].rank, Images());
-
- for (size_t i = 0; i < delta.moved.size(); ++i)
- db_->UpdatePageRank(delta.moved[i].url, delta.moved[i].rank);
+ db_->ApplyDelta(delta);
if (record_or_not == RECORD_HISTOGRAM_YES) {
UMA_HISTOGRAM_TIMES("History.FirstUpdateTime",
diff --git a/chromium/components/history/core/browser/top_sites_database.cc b/chromium/components/history/core/browser/top_sites_database.cc
index 435930053a2..520a0d32ae5 100644
--- a/chromium/components/history/core/browser/top_sites_database.cc
+++ b/chromium/components/history/core/browser/top_sites_database.cc
@@ -21,7 +21,6 @@
#include "sql/connection.h"
#include "sql/recovery.h"
#include "sql/statement.h"
-#include "sql/transaction.h"
#include "third_party/sqlite/sqlite3.h"
namespace history {
@@ -382,6 +381,26 @@ bool TopSitesDatabase::InitImpl(const base::FilePath& db_name) {
return true;
}
+void TopSitesDatabase::ApplyDelta(const TopSitesDelta& delta) {
+ sql::Transaction transaction(db_.get());
+ transaction.Begin();
+
+ for (size_t i = 0; i < delta.deleted.size(); ++i) {
+ if (!RemoveURLNoTransaction(delta.deleted[i]))
+ return;
+ }
+
+ for (size_t i = 0; i < delta.added.size(); ++i) {
+ SetPageThumbnailNoTransaction(delta.added[i].url, delta.added[i].rank,
+ Images());
+ }
+
+ for (size_t i = 0; i < delta.moved.size(); ++i)
+ UpdatePageRankNoTransaction(delta.moved[i].url, delta.moved[i].rank);
+
+ transaction.Commit();
+}
+
bool TopSitesDatabase::UpgradeToVersion3() {
// Add 'last_forced' column.
if (!db_->Execute(
@@ -416,8 +435,8 @@ void TopSitesDatabase::GetPageThumbnails(MostVisitedURLList* urls,
GURL gurl(statement.ColumnString(0));
url.url = gurl;
url.title = statement.ColumnString16(2);
- url.last_forced_time =
- base::Time::FromInternalValue(statement.ColumnInt64(10));
+ url.last_forced_time = base::Time() + base::TimeDelta::FromMicroseconds(
+ statement.ColumnInt64(10));
std::string redirects = statement.ColumnString(4);
SetRedirects(redirects, &url);
urls->push_back(url);
@@ -431,18 +450,46 @@ void TopSitesDatabase::GetPageThumbnails(MostVisitedURLList* urls,
thumbnail.thumbnail_score.good_clipping = statement.ColumnBool(6);
thumbnail.thumbnail_score.at_top = statement.ColumnBool(7);
thumbnail.thumbnail_score.time_at_snapshot =
- base::Time::FromInternalValue(statement.ColumnInt64(8));
+ base::Time() +
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(8));
thumbnail.thumbnail_score.load_completed = statement.ColumnBool(9);
(*thumbnails)[gurl] = thumbnail;
}
}
+bool TopSitesDatabase::GetPageThumbnail(const GURL& url, Images* thumbnail) {
+ sql::Statement statement(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated "
+ "FROM thumbnails WHERE url=?"));
+ statement.BindString(0, url.spec());
+ if (!statement.Step())
+ return false;
+
+ std::vector<unsigned char> data;
+ statement.ColumnBlobAsVector(0, &data);
+ thumbnail->thumbnail = base::RefCountedBytes::TakeVector(&data);
+ thumbnail->thumbnail_score.boring_score = statement.ColumnDouble(1);
+ thumbnail->thumbnail_score.good_clipping = statement.ColumnBool(2);
+ thumbnail->thumbnail_score.at_top = statement.ColumnBool(3);
+ thumbnail->thumbnail_score.time_at_snapshot =
+ base::Time() +
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(4));
+ return true;
+}
+
void TopSitesDatabase::SetPageThumbnail(const MostVisitedURL& url,
int new_rank,
const Images& thumbnail) {
sql::Transaction transaction(db_.get());
transaction.Begin();
+ SetPageThumbnailNoTransaction(url, new_rank, thumbnail);
+ transaction.Commit();
+}
+void TopSitesDatabase::SetPageThumbnailNoTransaction(const MostVisitedURL& url,
+ int new_rank,
+ const Images& thumbnail) {
int rank = GetURLRank(url);
if (rank == kRankOfNonExistingURL) {
AddPageThumbnail(url, new_rank, thumbnail);
@@ -450,35 +497,6 @@ void TopSitesDatabase::SetPageThumbnail(const MostVisitedURL& url,
UpdatePageRankNoTransaction(url, new_rank);
UpdatePageThumbnail(url, thumbnail);
}
-
- transaction.Commit();
-}
-
-bool TopSitesDatabase::UpdatePageThumbnail(const MostVisitedURL& url,
- const Images& thumbnail) {
- sql::Statement statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails SET "
- "title = ?, thumbnail = ?, redirects = ?, "
- "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, "
- "load_completed = ?, last_forced = ?"
- "WHERE url = ? "));
- statement.BindString16(0, url.title);
- if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) {
- statement.BindBlob(1, thumbnail.thumbnail->front(),
- static_cast<int>(thumbnail.thumbnail->size()));
- }
- statement.BindString(2, GetRedirects(url));
- const ThumbnailScore& score = thumbnail.thumbnail_score;
- statement.BindDouble(3, score.boring_score);
- statement.BindBool(4, score.good_clipping);
- statement.BindBool(5, score.at_top);
- statement.BindInt64(6, score.time_at_snapshot.ToInternalValue());
- statement.BindBool(7, score.load_completed);
- statement.BindInt64(8, url.last_forced_time.ToInternalValue());
- statement.BindString(9, url.url.spec());
-
- return statement.Run();
}
void TopSitesDatabase::AddPageThumbnail(const MostVisitedURL& url,
@@ -502,9 +520,10 @@ void TopSitesDatabase::AddPageThumbnail(const MostVisitedURL& url,
statement.BindDouble(5, score.boring_score);
statement.BindBool(6, score.good_clipping);
statement.BindBool(7, score.at_top);
- statement.BindInt64(8, score.time_at_snapshot.ToInternalValue());
+ statement.BindInt64(8,
+ score.time_at_snapshot.since_origin().InMicroseconds());
statement.BindBool(9, score.load_completed);
- int64_t last_forced = url.last_forced_time.ToInternalValue();
+ int64_t last_forced = url.last_forced_time.since_origin().InMicroseconds();
DCHECK((last_forced == 0) == (new_rank != kRankOfForcedURL))
<< "Thumbnail without a forced time stamp has a forced rank, or the "
<< "opposite.";
@@ -517,18 +536,46 @@ void TopSitesDatabase::AddPageThumbnail(const MostVisitedURL& url,
UpdatePageRankNoTransaction(url, new_rank);
}
-void TopSitesDatabase::UpdatePageRank(const MostVisitedURL& url, int new_rank) {
- DCHECK((url.last_forced_time.ToInternalValue() == 0) ==
- (new_rank != kRankOfForcedURL))
- << "Thumbnail without a forced time stamp has a forced rank, or the "
- << "opposite.";
- sql::Transaction transaction(db_.get());
- transaction.Begin();
- UpdatePageRankNoTransaction(url, new_rank);
- transaction.Commit();
+bool TopSitesDatabase::UpdatePageThumbnail(const MostVisitedURL& url,
+ const Images& thumbnail) {
+ sql::Statement statement(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "UPDATE thumbnails SET "
+ "title = ?, thumbnail = ?, redirects = ?, "
+ "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, "
+ "load_completed = ?, last_forced = ?"
+ "WHERE url = ? "));
+ statement.BindString16(0, url.title);
+ if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) {
+ statement.BindBlob(1, thumbnail.thumbnail->front(),
+ static_cast<int>(thumbnail.thumbnail->size()));
+ }
+ statement.BindString(2, GetRedirects(url));
+ const ThumbnailScore& score = thumbnail.thumbnail_score;
+ statement.BindDouble(3, score.boring_score);
+ statement.BindBool(4, score.good_clipping);
+ statement.BindBool(5, score.at_top);
+ statement.BindInt64(6,
+ score.time_at_snapshot.since_origin().InMicroseconds());
+ statement.BindBool(7, score.load_completed);
+ statement.BindInt64(8, url.last_forced_time.since_origin().InMicroseconds());
+ statement.BindString(9, url.url.spec());
+
+ return statement.Run();
+}
+
+int TopSitesDatabase::GetURLRank(const MostVisitedURL& url) {
+ sql::Statement select_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "SELECT url_rank "
+ "FROM thumbnails WHERE url=?"));
+ select_statement.BindString(0, url.url.spec());
+ if (select_statement.Step())
+ return select_statement.ColumnInt(0);
+
+ return kRankOfNonExistingURL;
}
-// Caller should have a transaction open.
void TopSitesDatabase::UpdatePageRankNoTransaction(const MostVisitedURL& url,
int new_rank) {
DCHECK_GT(db_->transaction_nesting(), 0);
@@ -548,22 +595,22 @@ void TopSitesDatabase::UpdatePageRankNoTransaction(const MostVisitedURL& url,
// From non-forced to forced, shift down.
// Example: 2 -> -1
// -1, -1, -1, 0, 1, [2 -> -1], [3 -> 2], [4 -> 3]
- sql::Statement shift_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = url_rank - 1 "
- "WHERE url_rank > ?"));
+ sql::Statement shift_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = url_rank - 1 "
+ "WHERE url_rank > ?"));
shift_statement.BindInt(0, prev_rank);
shift_statement.Run();
} else {
// From non-forced to non-forced, shift up.
// Example: 3 -> 1
// -1, -1, -1, 0, [1 -> 2], [2 -> 3], [3 -> 1], 4
- sql::Statement shift_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = url_rank + 1 "
- "WHERE url_rank >= ? AND url_rank < ?"));
+ sql::Statement shift_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = url_rank + 1 "
+ "WHERE url_rank >= ? AND url_rank < ?"));
shift_statement.BindInt(0, new_rank);
shift_statement.BindInt(1, prev_rank);
shift_statement.Run();
@@ -573,22 +620,22 @@ void TopSitesDatabase::UpdatePageRankNoTransaction(const MostVisitedURL& url,
// From non-forced to forced, shift up.
// Example: -1 -> 2
// -1, [-1 -> 2], -1, 0, 1, [2 -> 3], [3 -> 4], [4 -> 5]
- sql::Statement shift_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = url_rank + 1 "
- "WHERE url_rank >= ?"));
+ sql::Statement shift_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = url_rank + 1 "
+ "WHERE url_rank >= ?"));
shift_statement.BindInt(0, new_rank);
shift_statement.Run();
} else {
// From non-forced to non-forced, shift down.
// Example: 1 -> 3.
// -1, -1, -1, 0, [1 -> 3], [2 -> 1], [3 -> 2], 4
- sql::Statement shift_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = url_rank - 1 "
- "WHERE url_rank > ? AND url_rank <= ?"));
+ sql::Statement shift_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = url_rank - 1 "
+ "WHERE url_rank > ? AND url_rank <= ?"));
shift_statement.BindInt(0, prev_rank);
shift_statement.BindInt(1, new_rank);
shift_statement.Run();
@@ -597,79 +644,41 @@ void TopSitesDatabase::UpdatePageRankNoTransaction(const MostVisitedURL& url,
// Set the url's rank and last_forced, since the latter changes when a URL
// goes from forced to non-forced and vice-versa.
- sql::Statement set_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = ?, last_forced = ? "
- "WHERE url == ?"));
+ sql::Statement set_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = ?, last_forced = ? "
+ "WHERE url == ?"));
set_statement.BindInt(0, new_rank);
- set_statement.BindInt64(1, url.last_forced_time.ToInternalValue());
+ set_statement.BindInt64(1,
+ url.last_forced_time.since_origin().InMicroseconds());
set_statement.BindString(2, url.url.spec());
set_statement.Run();
}
-bool TopSitesDatabase::GetPageThumbnail(const GURL& url, Images* thumbnail) {
- sql::Statement statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated "
- "FROM thumbnails WHERE url=?"));
- statement.BindString(0, url.spec());
- if (!statement.Step())
- return false;
-
- std::vector<unsigned char> data;
- statement.ColumnBlobAsVector(0, &data);
- thumbnail->thumbnail = base::RefCountedBytes::TakeVector(&data);
- thumbnail->thumbnail_score.boring_score = statement.ColumnDouble(1);
- thumbnail->thumbnail_score.good_clipping = statement.ColumnBool(2);
- thumbnail->thumbnail_score.at_top = statement.ColumnBool(3);
- thumbnail->thumbnail_score.time_at_snapshot =
- base::Time::FromInternalValue(statement.ColumnInt64(4));
- return true;
-}
-
-int TopSitesDatabase::GetURLRank(const MostVisitedURL& url) {
- sql::Statement select_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "SELECT url_rank "
- "FROM thumbnails WHERE url=?"));
- select_statement.BindString(0, url.url.spec());
- if (select_statement.Step())
- return select_statement.ColumnInt(0);
-
- return kRankOfNonExistingURL;
-}
-
-// Remove the record for this URL. Returns true iff removed successfully.
-bool TopSitesDatabase::RemoveURL(const MostVisitedURL& url) {
+bool TopSitesDatabase::RemoveURLNoTransaction(const MostVisitedURL& url) {
int old_rank = GetURLRank(url);
if (old_rank == kRankOfNonExistingURL)
- return false;
+ return true;
- sql::Transaction transaction(db_.get());
- transaction.Begin();
if (old_rank != kRankOfForcedURL) {
// Decrement all following ranks.
- sql::Statement shift_statement(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "UPDATE thumbnails "
- "SET url_rank = url_rank - 1 "
- "WHERE url_rank > ?"));
+ sql::Statement shift_statement(
+ db_->GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE thumbnails "
+ "SET url_rank = url_rank - 1 "
+ "WHERE url_rank > ?"));
shift_statement.BindInt(0, old_rank);
if (!shift_statement.Run())
return false;
}
- sql::Statement delete_statement(
- db_->GetCachedStatement(SQL_FROM_HERE,
- "DELETE FROM thumbnails WHERE url = ?"));
+ sql::Statement delete_statement(db_->GetCachedStatement(
+ SQL_FROM_HERE, "DELETE FROM thumbnails WHERE url = ?"));
delete_statement.BindString(0, url.url.spec());
- if (!delete_statement.Run())
- return false;
-
- return transaction.Commit();
+ return delete_statement.Run();
}
sql::Connection* TopSitesDatabase::CreateDB(const base::FilePath& db_name) {
diff --git a/chromium/components/history/core/browser/top_sites_database.h b/chromium/components/history/core/browser/top_sites_database.h
index 3556db1d20e..981d2d31b59 100644
--- a/chromium/components/history/core/browser/top_sites_database.h
+++ b/chromium/components/history/core/browser/top_sites_database.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "components/history/core/browser/history_types.h"
#include "sql/meta_table.h"
+#include "sql/transaction.h"
namespace base {
class FilePath;
@@ -32,31 +33,22 @@ class TopSitesDatabase {
// Returns true on success. If false, no other functions should be called.
bool Init(const base::FilePath& db_name);
- // Thumbnails ----------------------------------------------------------------
+ // Updates the database according to the changes recorded in |delta|.
+ void ApplyDelta(const TopSitesDelta& delta);
// Returns a list of all URLs currently in the table.
// WARNING: clears both input arguments.
void GetPageThumbnails(MostVisitedURLList* urls,
std::map<GURL, Images>* thumbnails);
- // Set a thumbnail for a URL. |url_rank| is the position of the URL
+ // Sets a thumbnail for a URL. |new_rank| is the position of the URL
// in the list of TopURLs, zero-based.
- // If the URL is not in the table, add it. If it is, replace its
- // thumbnail and rank. Shift the ranks of other URLs if necessary.
+ // If the URL is not in the table, add it. If it is, replaces its
+ // thumbnail and rank. Shifts the ranks of other URLs if necessary.
void SetPageThumbnail(const MostVisitedURL& url,
int new_rank,
const Images& thumbnail);
- // Sets the rank for a given URL. The URL must be in the database.
- // Use SetPageThumbnail if it's not.
- void UpdatePageRank(const MostVisitedURL& url, int new_rank);
-
- // Get a thumbnail for a given page. Returns true iff we have the thumbnail.
- bool GetPageThumbnail(const GURL& url, Images* thumbnail);
-
- // Remove the record for this URL. Returns true iff removed successfully.
- bool RemoveURL(const MostVisitedURL& url);
-
private:
FRIEND_TEST_ALL_PREFIXES(TopSitesDatabaseTest, Version1);
FRIEND_TEST_ALL_PREFIXES(TopSitesDatabaseTest, Version2);
@@ -77,13 +69,22 @@ class TopSitesDatabase {
// upgrade was successful.
bool UpgradeToVersion3();
+ // Sets a thumbnail for a URL. |new_rank| is the position of the URL
+ // in the list of TopURLs, zero-based.
+ // If the URL is not in the table, add it. If it is, replaces its
+ // thumbnail and rank. Shifts the ranks of other URLs if necessary.
+ // Should be called within an open transaction.
+ void SetPageThumbnailNoTransaction(const MostVisitedURL& url,
+ int new_rank,
+ const Images& thumbnail);
+
// Adds a new URL to the database.
void AddPageThumbnail(const MostVisitedURL& url,
int new_rank,
const Images& thumbnail);
- // Sets the page rank. Should be called within an open transaction.
- void UpdatePageRankNoTransaction(const MostVisitedURL& url, int new_rank);
+ // Gets a thumbnail for a given page. Returns true iff we have the thumbnail.
+ bool GetPageThumbnail(const GURL& url, Images* thumbnail);
// Updates thumbnail of a URL that's already in the database.
// Returns true if the database query succeeds.
@@ -92,6 +93,15 @@ class TopSitesDatabase {
// Returns |url|'s current rank or kRankOfNonExistingURL if not present.
int GetURLRank(const MostVisitedURL& url);
+ // Sets the rank for a given URL. The URL must be in the database.
+ // Uses SetPageThumbnail if it's not. Should be called within an open
+ // transaction.
+ void UpdatePageRankNoTransaction(const MostVisitedURL& url, int new_rank);
+
+ // Removes the record for this URL. Returns false iff there is a failure in
+ // running the statement. Should be called within an open transaction.
+ bool RemoveURLNoTransaction(const MostVisitedURL& url);
+
// Helper function to implement internals of Init(). This allows
// Init() to retry in case of failure, since some failures will
// invoke recovery code.
diff --git a/chromium/components/history/core/browser/top_sites_database_unittest.cc b/chromium/components/history/core/browser/top_sites_database_unittest.cc
index 29683551742..4788bc197fd 100644
--- a/chromium/components/history/core/browser/top_sites_database_unittest.cc
+++ b/chromium/components/history/core/browser/top_sites_database_unittest.cc
@@ -118,7 +118,11 @@ TEST_F(TopSitesDatabaseTest, Version3) {
EXPECT_TRUE(!memcmp(thumbnails[urls[0].url].thumbnail->front(),
kGoogleThumbnail, sizeof(kGoogleThumbnail) - 1));
- ASSERT_TRUE(db.RemoveURL(urls[1]));
+ sql::Transaction transaction(db.db_.get());
+ transaction.Begin();
+ ASSERT_TRUE(db.RemoveURLNoTransaction(urls[1]));
+ transaction.Commit();
+
db.GetPageThumbnails(&urls, &thumbnails);
ASSERT_EQ(2u, urls.size());
ASSERT_EQ(2u, thumbnails.size());
@@ -370,9 +374,13 @@ TEST_F(TopSitesDatabaseTest, AddRemoveEditThumbnails) {
EXPECT_EQ(kUrl0, urls[2].url);
EXPECT_EQ(mapsUrl, urls[3].url);
- // Change a non-forced URL to forced using UpdatePageRank.
+ sql::Transaction transaction(db.db_.get());
+
+ // Change a non-forced URL to forced using UpdatePageRankNoTransaction.
url1.last_forced_time = base::Time::FromJsTime(792219600000); // 8/2/1995
- db.UpdatePageRank(url1, TopSitesDatabase::kRankOfForcedURL);
+ transaction.Begin();
+ db.UpdatePageRankNoTransaction(url1, TopSitesDatabase::kRankOfForcedURL);
+ transaction.Commit();
db.GetPageThumbnails(&urls, &thumbnails);
ASSERT_EQ(6u, urls.size());
@@ -394,8 +402,11 @@ TEST_F(TopSitesDatabaseTest, AddRemoveEditThumbnails) {
EXPECT_EQ(kUrl0, urls[2].url);
EXPECT_EQ(plusUrl, urls[3].url); // Plus moves to second non-forced URL.
- // Change a non-forced URL to earlier non-forced using UpdatePageRank.
- db.UpdatePageRank(url3, 0);
+ // Change a non-forced URL to earlier non-forced using
+ // UpdatePageRankNoTransaction.
+ transaction.Begin();
+ db.UpdatePageRankNoTransaction(url3, 0);
+ transaction.Commit();
db.GetPageThumbnails(&urls, &thumbnails);
ASSERT_EQ(6u, urls.size());
@@ -417,7 +428,9 @@ TEST_F(TopSitesDatabaseTest, AddRemoveEditThumbnails) {
EXPECT_EQ(plusUrl, urls[4].url); // Plus moves to third non-forced URL.
// Remove a non-forced URL.
- db.RemoveURL(url3);
+ transaction.Begin();
+ ASSERT_TRUE(db.RemoveURLNoTransaction(url3));
+ transaction.Commit();
db.GetPageThumbnails(&urls, &thumbnails);
ASSERT_EQ(5u, urls.size());
@@ -427,7 +440,9 @@ TEST_F(TopSitesDatabaseTest, AddRemoveEditThumbnails) {
EXPECT_EQ(kUrl0, urls[2].url);
// Remove a forced URL.
- db.RemoveURL(url2);
+ transaction.Begin();
+ ASSERT_TRUE(db.RemoveURLNoTransaction(url2));
+ transaction.Commit();
db.GetPageThumbnails(&urls, &thumbnails);
ASSERT_EQ(4u, urls.size());
@@ -436,4 +451,43 @@ TEST_F(TopSitesDatabaseTest, AddRemoveEditThumbnails) {
EXPECT_EQ(kUrl0, urls[1].url);
}
+TEST_F(TopSitesDatabaseTest, ApplyDelta) {
+ ASSERT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v3.sql"));
+
+ TopSitesDatabase db;
+ ASSERT_TRUE(db.Init(file_name_));
+
+ GURL mapsUrl = GURL("http://maps.google.com/");
+
+ TopSitesDelta delta;
+ // Delete kUrl0. Now db has kUrl1 and kUrl2.
+ MostVisitedURL url_to_delete(kUrl0, base::ASCIIToUTF16("Google"));
+ delta.deleted.push_back(url_to_delete);
+
+ // Add a new URL, not forced, rank = 0. Now db has mapsUrl, kUrl1 and kUrl2.
+ MostVisitedURLWithRank url_to_add;
+ url_to_add.url = MostVisitedURL(mapsUrl, base::ASCIIToUTF16("Google Maps"));
+ url_to_add.rank = 0;
+ delta.added.push_back(url_to_add);
+
+ // Move kUrl1 by updating its rank to 2. Now db has mapsUrl, kUrl2 and kUrl1.
+ MostVisitedURLWithRank url_to_move;
+ url_to_move.url = MostVisitedURL(kUrl1, base::ASCIIToUTF16("Google Chrome"));
+ url_to_move.rank = 2;
+ delta.moved.push_back(url_to_move);
+
+ // Update db.
+ db.ApplyDelta(delta);
+
+ // Read db and verify.
+ MostVisitedURLList urls;
+ std::map<GURL, Images> thumbnails;
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ ASSERT_EQ(3u, thumbnails.size());
+ EXPECT_EQ(mapsUrl, urls[0].url);
+ EXPECT_EQ(kUrl2, urls[1].url);
+ EXPECT_EQ(kUrl1, urls[2].url);
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/top_sites_impl.cc b/chromium/components/history/core/browser/top_sites_impl.cc
index aa758327087..daf38913134 100644
--- a/chromium/components/history/core/browser/top_sites_impl.cc
+++ b/chromium/components/history/core/browser/top_sites_impl.cc
@@ -65,28 +65,39 @@ bool ForcedURLComparator(const MostVisitedURL& first,
return first.last_forced_time < second.last_forced_time;
}
-// How many non-forced top sites to store in the cache.
-const size_t kNonForcedTopSitesNumber = 20;
+// Checks if the titles stored in |old_list| and |new_list| have changes.
+bool DoTitlesDiffer(const MostVisitedURLList& old_list,
+ const MostVisitedURLList& new_list) {
+ // If the two lists have different sizes, the most visited titles are
+ // considered to have changes.
+ if (old_list.size() != new_list.size())
+ return true;
-// How many forced top sites to store in the cache.
-const size_t kForcedTopSitesNumber = 20;
+ return !std::equal(std::begin(old_list), std::end(old_list),
+ std::begin(new_list),
+ [](const auto& old_item_ptr, const auto& new_item_ptr) {
+ return old_item_ptr.title == new_item_ptr.title;
+ });
+}
// Max number of temporary images we'll cache. See comment above
// temp_images_ for details.
const size_t kMaxTempTopImages = 8;
const int kDaysOfHistory = 90;
-// Time from startup to first HistoryService query.
-const int64_t kUpdateIntervalSecs = 15;
-// Intervals between requests to HistoryService.
-const int64_t kMinUpdateIntervalMinutes = 1;
+
+// The delay for the first HistoryService query at startup.
+constexpr base::TimeDelta kFirstDelayAtStartup =
+ base::TimeDelta::FromSeconds(15);
+
+// The delay for the all HistoryService queries other than the first one.
#if defined(OS_IOS) || defined(OS_ANDROID)
// On mobile, having the max at 60 minutes results in the topsites database
// being not updated often enough since the app isn't usually running for long
// stretches of time.
-const int64_t kMaxUpdateIntervalMinutes = 5;
+constexpr base::TimeDelta kDelayForUpdates = base::TimeDelta::FromMinutes(5);
#else
-const int64_t kMaxUpdateIntervalMinutes = 60;
+constexpr base::TimeDelta kDelayForUpdates = base::TimeDelta::FromMinutes(60);
#endif // defined(OS_IOS) || defined(OS_ANDROID)
// Use 100 quality (highest quality) because we're very sensitive to
@@ -109,7 +120,6 @@ TopSitesImpl::TopSitesImpl(PrefService* pref_service,
: backend_(nullptr),
cache_(base::MakeUnique<TopSitesCache>()),
thread_safe_cache_(base::MakeUnique<TopSitesCache>()),
- last_num_urls_changed_(0),
prepopulated_pages_(prepopulated_pages),
pref_service_(pref_service),
history_service_(history_service),
@@ -198,7 +208,7 @@ bool TopSitesImpl::GetPageThumbnail(
for (const auto& prepopulated_page : prepopulated_pages_) {
if (url == prepopulated_page.most_visited.url) {
*bytes =
- ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
+ ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
prepopulated_page.thumbnail_id, ui::SCALE_FACTOR_100P);
return true;
}
@@ -256,10 +266,8 @@ static int IndexOf(const MostVisitedURLList& urls, const GURL& url) {
void TopSitesImpl::SyncWithHistory() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (loaded_) {
- timer_.Stop();
+ if (loaded_)
StartQueryForMostVisited();
- }
}
bool TopSitesImpl::HasBlacklistedItems() const {
@@ -373,14 +381,11 @@ bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) {
void TopSitesImpl::OnNavigationCommitted(const GURL& url) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!loaded_ || IsNonForcedFull())
+ if (!loaded_)
return;
- if (!cache_->IsKnownURL(url) && can_add_url_to_history_.Run(url)) {
- // To avoid slamming history we throttle requests when the url updates. To
- // do otherwise negatively impacts perf tests.
- RestartQueryForTopSitesTimer(GetUpdateDelay());
- }
+ if (can_add_url_to_history_.Run(url))
+ ScheduleUpdateTimer();
}
void TopSitesImpl::ShutdownOnUIThread() {
@@ -403,6 +408,8 @@ TopSitesImpl::~TopSitesImpl() = default;
void TopSitesImpl::StartQueryForMostVisited() {
DCHECK(loaded_);
+ timer_.Stop();
+
if (!history_service_)
return;
@@ -604,10 +611,6 @@ void TopSitesImpl::AddTemporaryThumbnail(const GURL& url,
temp_images_.push_back(image);
}
-void TopSitesImpl::TimerFired() {
- StartQueryForMostVisited();
-}
-
// static
int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
const GURL& url) {
@@ -639,9 +642,9 @@ size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) const {
std::set<GURL> all_new_urls;
size_t num_forced = 0;
for (size_t i = 0; i < new_list->size(); ++i) {
- for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++) {
+ for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++)
all_new_urls.insert((*new_list)[i].redirects[j]);
- }
+
if (!(*new_list)[i].last_forced_time.is_null())
++num_forced;
}
@@ -708,16 +711,6 @@ std::string TopSitesImpl::GetURLHash(const GURL& url) {
return base::MD5String(url.spec());
}
-base::TimeDelta TopSitesImpl::GetUpdateDelay() const {
- if (cache_->top_sites().size() <= prepopulated_pages_.size())
- return base::TimeDelta::FromSeconds(30);
-
- int64_t range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes;
- int64_t minutes = kMaxUpdateIntervalMinutes -
- last_num_urls_changed_ * range / cache_->top_sites().size();
- return base::TimeDelta::FromMinutes(minutes);
-}
-
void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
const CallLocation location) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -746,11 +739,16 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
histogram_recorded_ = true;
}
+ bool should_notify_observers = false;
+ // If there is a change in urls, update the db and notify observers.
if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) {
backend_->UpdateTopSites(delta, record_or_not);
+ should_notify_observers = true;
}
-
- last_num_urls_changed_ = delta.added.size() + delta.moved.size();
+ // If there is no url change in top sites, check if the titles have changes.
+ // Notify observers if there's a change in titles.
+ if (!should_notify_observers)
+ should_notify_observers = DoTitlesDiffer(cache_->top_sites(), top_sites);
// We always do the following steps (setting top sites in cache, and resetting
// thread safe cache ...) as this method is invoked during startup at which
@@ -789,14 +787,14 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
ResetThreadSafeCache();
ResetThreadSafeImageCache();
- if (location == CALL_LOCATION_FROM_FORCED_URLS)
- NotifyTopSitesChanged(TopSitesObserver::ChangeReason::FORCED_URL);
- else
- NotifyTopSitesChanged(TopSitesObserver::ChangeReason::MOST_VISITED);
- // Restart the timer that queries history for top sites. This is done to
- // ensure we stay in sync with history.
- RestartQueryForTopSitesTimer(GetUpdateDelay());
+ if (should_notify_observers) {
+ if (location == CALL_LOCATION_FROM_FORCED_URLS)
+ NotifyTopSitesChanged(TopSitesObserver::ChangeReason::FORCED_URL);
+ else
+ NotifyTopSitesChanged(TopSitesObserver::ChangeReason::MOST_VISITED);
+ }
+
}
int TopSitesImpl::num_results_to_request_from_history() const {
@@ -854,15 +852,12 @@ void TopSitesImpl::ResetThreadSafeImageCache() {
thread_safe_cache_->SetThumbnails(cache_->images());
}
-void TopSitesImpl::RestartQueryForTopSitesTimer(base::TimeDelta delta) {
- if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) <
- (base::TimeTicks::Now() + delta))) {
+void TopSitesImpl::ScheduleUpdateTimer() {
+ if (timer_.IsRunning())
return;
- }
- timer_start_time_ = base::TimeTicks::Now();
- timer_.Stop();
- timer_.Start(FROM_HERE, delta, this, &TopSitesImpl::TimerFired);
+ timer_.Start(FROM_HERE, kDelayForUpdates, this,
+ &TopSitesImpl::StartQueryForMostVisited);
}
void TopSitesImpl::OnGotMostVisitedThumbnails(
@@ -881,8 +876,8 @@ void TopSitesImpl::OnGotMostVisitedThumbnails(
MoveStateToLoaded();
// Start a timer that refreshes top sites from history.
- RestartQueryForTopSitesTimer(
- base::TimeDelta::FromSeconds(kUpdateIntervalSecs));
+ timer_.Start(FROM_HERE, kFirstDelayAtStartup, this,
+ &TopSitesImpl::StartQueryForMostVisited);
}
void TopSitesImpl::OnTopSitesAvailableFromHistory(
diff --git a/chromium/components/history/core/browser/top_sites_impl.h b/chromium/components/history/core/browser/top_sites_impl.h
index e8d10234207..7e6cb3581c9 100644
--- a/chromium/components/history/core/browser/top_sites_impl.h
+++ b/chromium/components/history/core/browser/top_sites_impl.h
@@ -57,6 +57,12 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// callable multiple time and during the whole lifetime of TopSitesImpl.
using CanAddURLToHistoryFn = base::Callback<bool(const GURL&)>;
+ // How many non-forced top sites to store in the cache.
+ static constexpr size_t kNonForcedTopSitesNumber = 10;
+
+ // How many forced top sites to store in the cache.
+ static constexpr size_t kForcedTopSitesNumber = 10;
+
TopSitesImpl(PrefService* pref_service,
HistoryService* history_service,
const PrepopulatedPageList& prepopulated_pages,
@@ -143,6 +149,9 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
typedef std::list<TempImage> TempImages;
typedef std::vector<PendingCallback> PendingCallbacks;
+ // Starts to query most visited URLs from history database instantly.
+ // Also cancels any pending queries requested in a delayed manner by
+ // cancelling the timer.
void StartQueryForMostVisited();
// Generates the diff of things that happened between "old" and "new."
@@ -188,26 +197,23 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// in |temp_images_|.
void RemoveTemporaryThumbnailByURL(const GURL& url);
- // Add a thumbnail for an unknown url. See |temp_images_|.
+ // Adds a thumbnail for an unknown url. See |temp_images_|.
void AddTemporaryThumbnail(const GURL& url,
base::RefCountedMemory* thumbnail,
const ThumbnailScore& score);
- // Called by our timer. Starts the query for the most visited sites.
- void TimerFired();
-
// Finds the given URL in the redirect chain for the given TopSite, and
// returns the distance from the destination in hops that the given URL is.
// The URL is assumed to be in the list. The destination is 0.
static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
const GURL& url);
- // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
+ // Adds prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
// Returns true if any pages were added.
bool AddPrepopulatedPages(MostVisitedURLList* urls,
size_t num_forced_urls) const;
- // Add all the forced URLs from |cache_| into |new_list|, making sure not to
+ // Adds all the forced URLs from |cache_| into |new_list|, making sure not to
// add any URL that's already in |new_list|'s non-forced URLs. The forced URLs
// in |cache_| and |new_list| are assumed to appear at the front of the list
// and be sorted in increasing |last_forced_time|. This will still be true
@@ -223,10 +229,6 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
static std::string GetURLHash(const GURL& url);
- // Returns the delay until the next update of history is needed.
- // Uses |last_num_urls_changed_|.
- base::TimeDelta GetUpdateDelay() const;
-
// Updates URLs in |cache_| and the db (in the background).
// The non-forced URLs in |new_top_sites| replace those in |cache_|.
// The forced URLs of |new_top_sites| are merged with those in |cache_|,
@@ -249,8 +251,9 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
void ResetThreadSafeImageCache();
- // Stops and starts timer with a delay of |delta|.
- void RestartQueryForTopSitesTimer(base::TimeDelta delta);
+ // Schedules a timer to update top sites with a delay.
+ // Does nothing if there is already a request queued.
+ void ScheduleUpdateTimer();
// Callback from TopSites with the top sites/thumbnails. Should be called
// from the UI thread.
@@ -286,16 +289,10 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Task tracker for history and backend requests.
base::CancelableTaskTracker cancelable_task_tracker_;
- // Timer that asks history for the top sites. This is used to make sure our
- // data stays in sync with history.
+ // Timer that asks history for the top sites. This is used to coalesce
+ // requests that are generated in quick succession.
base::OneShotTimer timer_;
- // The time we started |timer_| at. Only valid if |timer_| is running.
- base::TimeTicks timer_start_time_;
-
- // The number of URLs changed on the last update.
- size_t last_num_urls_changed_;
-
// The pending requests for the top sites list. Can only be non-empty at
// startup. After we read the top sites from the DB, we'll always have a
// cached list and be able to run callbacks immediately.
diff --git a/chromium/components/history/core/browser/top_sites_impl_unittest.cc b/chromium/components/history/core/browser/top_sites_impl_unittest.cc
index 00d1e10793b..682116d8c2c 100644
--- a/chromium/components/history/core/browser/top_sites_impl_unittest.cc
+++ b/chromium/components/history/core/browser/top_sites_impl_unittest.cc
@@ -255,14 +255,6 @@ class TopSitesImplTest : public HistoryUnitTestBase {
void StartQueryForMostVisited() { top_sites()->StartQueryForMostVisited(); }
- void SetLastNumUrlsChanged(size_t value) {
- top_sites()->last_num_urls_changed_ = value;
- }
-
- size_t last_num_urls_changed() { return top_sites()->last_num_urls_changed_; }
-
- base::TimeDelta GetUpdateDelay() { return top_sites()->GetUpdateDelay(); }
-
bool IsTopSitesLoaded() { return top_sites()->loaded_; }
bool AddPrepopulatedPages(MostVisitedURLList* urls) {
@@ -326,8 +318,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
// Helper function for appending a URL to a vector of "most visited" URLs,
// using the default values for everything but the URL.
-static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
- const GURL& url) {
+void AppendMostVisitedURL(const GURL& url, std::vector<MostVisitedURL>* list) {
MostVisitedURL mv;
mv.url = url;
mv.redirects.push_back(url);
@@ -336,9 +327,9 @@ static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
// Helper function for appending a URL to a vector of "most visited" URLs,
// using the default values for everything but the URL.
-static void AppendForcedMostVisitedURL(std::vector<MostVisitedURL>* list,
- const GURL& url,
- double last_forced_time) {
+void AppendForcedMostVisitedURL(const GURL& url,
+ double last_forced_time,
+ std::vector<MostVisitedURL>* list) {
MostVisitedURL mv;
mv.url = url;
mv.last_forced_time = base::Time::FromJsTime(last_forced_time);
@@ -348,9 +339,9 @@ static void AppendForcedMostVisitedURL(std::vector<MostVisitedURL>* list,
// Same as AppendMostVisitedURL except that it adds a redirect from the first
// URL to the second.
-static void AppendMostVisitedURLWithRedirect(std::vector<MostVisitedURL>* list,
- const GURL& redirect_source,
- const GURL& redirect_dest) {
+void AppendMostVisitedURLWithRedirect(const GURL& redirect_source,
+ const GURL& redirect_dest,
+ std::vector<MostVisitedURL>* list) {
MostVisitedURL mv;
mv.url = redirect_dest;
mv.redirects.push_back(redirect_source);
@@ -358,6 +349,18 @@ static void AppendMostVisitedURLWithRedirect(std::vector<MostVisitedURL>* list,
list->push_back(mv);
}
+// Helper function for appending a URL to a vector of "most visited" URLs,
+// using the default values for everything but the URL and the title.
+void AppendMostVisitedURLwithTitle(const GURL& url,
+ const base::string16& title,
+ std::vector<MostVisitedURL>* list) {
+ MostVisitedURL mv;
+ mv.url = url;
+ mv.title = title;
+ mv.redirects.push_back(url);
+ list->push_back(mv);
+}
+
// Tests GetCanonicalURL.
TEST_F(TopSitesImplTest, GetCanonicalURL) {
// Have two chains:
@@ -368,8 +371,8 @@ TEST_F(TopSitesImplTest, GetCanonicalURL) {
GURL dest("http://www.google.com/");
std::vector<MostVisitedURL> most_visited;
- AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
- AppendMostVisitedURL(&most_visited, news);
+ AppendMostVisitedURLWithRedirect(source, dest, &most_visited);
+ AppendMostVisitedURL(news, &most_visited);
SetTopSites(most_visited);
// Random URLs not in the database are returned unchanged.
@@ -389,6 +392,70 @@ TEST_F(TopSitesImplTest, GetCanonicalURL) {
EXPECT_EQ(dest, result);
}
+class MockTopSitesObserver : public TopSitesObserver {
+ public:
+ MockTopSitesObserver() {}
+
+ // history::TopSitesObserver:
+ void TopSitesLoaded(TopSites* top_sites) override {}
+ void TopSitesChanged(TopSites* top_sites,
+ ChangeReason change_reason) override {
+ is_notified_ = true;
+ }
+
+ void ResetIsNotifiedState() { is_notified_ = false; }
+ bool is_notified() const { return is_notified_; }
+
+ private:
+ bool is_notified_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MockTopSitesObserver);
+};
+
+// Tests DoTitlesDiffer.
+TEST_F(TopSitesImplTest, DoTitlesDiffer) {
+ GURL url_1("http://url1/");
+ GURL url_2("http://url2/");
+ base::string16 title_1(base::ASCIIToUTF16("title1"));
+ base::string16 title_2(base::ASCIIToUTF16("title2"));
+
+ MockTopSitesObserver observer;
+ top_sites()->AddObserver(&observer);
+
+ // TopSites has a new list of sites and should notify its observers.
+ std::vector<MostVisitedURL> list_1;
+ AppendMostVisitedURLwithTitle(url_1, title_1, &list_1);
+ SetTopSites(list_1);
+ EXPECT_TRUE(observer.is_notified());
+ observer.ResetIsNotifiedState();
+ EXPECT_FALSE(observer.is_notified());
+
+ // list_1 and list_2 have different sizes. TopSites should notify its
+ // observers.
+ std::vector<MostVisitedURL> list_2;
+ AppendMostVisitedURLwithTitle(url_1, title_1, &list_2);
+ AppendMostVisitedURLwithTitle(url_2, title_2, &list_2);
+ SetTopSites(list_2);
+ EXPECT_TRUE(observer.is_notified());
+ observer.ResetIsNotifiedState();
+ EXPECT_FALSE(observer.is_notified());
+
+ // list_1 and list_2 are exactly the same now. TopSites should not notify its
+ // observers.
+ AppendMostVisitedURLwithTitle(url_2, title_2, &list_1);
+ SetTopSites(list_1);
+ EXPECT_FALSE(observer.is_notified());
+
+ // Change |url_2|'s title to |title_1| in list_2. The two lists are different
+ // in titles now. TopSites should notify its observers.
+ list_2.pop_back();
+ AppendMostVisitedURLwithTitle(url_2, title_1, &list_2);
+ SetTopSites(list_2);
+ EXPECT_TRUE(observer.is_notified());
+
+ top_sites()->RemoveObserver(&observer);
+}
+
// Tests DiffMostVisited.
TEST_F(TopSitesImplTest, DiffMostVisited) {
GURL stays_the_same("http://staysthesame/");
@@ -398,18 +465,18 @@ TEST_F(TopSitesImplTest, DiffMostVisited) {
GURL gets_moved_1("http://getsmoved1/");
std::vector<MostVisitedURL> old_list;
- AppendMostVisitedURL(&old_list, stays_the_same); // 0 (unchanged)
- AppendMostVisitedURL(&old_list, gets_deleted_1); // 1 (deleted)
- AppendMostVisitedURL(&old_list, gets_moved_1); // 2 (moved to 3)
+ AppendMostVisitedURL(stays_the_same, &old_list); // 0 (unchanged)
+ AppendMostVisitedURL(gets_deleted_1, &old_list); // 1 (deleted)
+ AppendMostVisitedURL(gets_moved_1, &old_list); // 2 (moved to 3)
std::vector<MostVisitedURL> new_list;
- AppendMostVisitedURL(&new_list, stays_the_same); // 0 (unchanged)
- AppendMostVisitedURL(&new_list, gets_added_1); // 1 (added)
- AppendMostVisitedURL(&new_list, gets_added_2); // 2 (added)
- AppendMostVisitedURL(&new_list, gets_moved_1); // 3 (moved from 2)
+ AppendMostVisitedURL(stays_the_same, &new_list); // 0 (unchanged)
+ AppendMostVisitedURL(gets_added_1, &new_list); // 1 (added)
+ AppendMostVisitedURL(gets_added_2, &new_list); // 2 (added)
+ AppendMostVisitedURL(gets_moved_1, &new_list); // 3 (moved from 2)
history::TopSitesDelta delta;
- history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
+ TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
ASSERT_EQ(2u, delta.added.size());
EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
@@ -442,29 +509,29 @@ TEST_F(TopSitesImplTest, DiffMostVisitedWithForced) {
GURL gets_moved_1("http://getsmoved1/");
std::vector<MostVisitedURL> old_list;
- AppendForcedMostVisitedURL(&old_list, stays_the_same_1, 1000);
- AppendForcedMostVisitedURL(&old_list, new_last_forced_time, 2000);
- AppendForcedMostVisitedURL(&old_list, stays_the_same_2, 3000);
- AppendForcedMostVisitedURL(&old_list, move_to_nonforced, 4000);
- AppendForcedMostVisitedURL(&old_list, gets_deleted_1, 5000);
- AppendMostVisitedURL(&old_list, move_to_forced);
- AppendMostVisitedURL(&old_list, stays_the_same_3);
- AppendMostVisitedURL(&old_list, gets_deleted_2);
- AppendMostVisitedURL(&old_list, gets_moved_1);
+ AppendForcedMostVisitedURL(stays_the_same_1, 1000, &old_list);
+ AppendForcedMostVisitedURL(new_last_forced_time, 2000, &old_list);
+ AppendForcedMostVisitedURL(stays_the_same_2, 3000, &old_list);
+ AppendForcedMostVisitedURL(move_to_nonforced, 4000, &old_list);
+ AppendForcedMostVisitedURL(gets_deleted_1, 5000, &old_list);
+ AppendMostVisitedURL(move_to_forced, &old_list);
+ AppendMostVisitedURL(stays_the_same_3, &old_list);
+ AppendMostVisitedURL(gets_deleted_2, &old_list);
+ AppendMostVisitedURL(gets_moved_1, &old_list);
std::vector<MostVisitedURL> new_list;
- AppendForcedMostVisitedURL(&new_list, stays_the_same_1, 1000);
- AppendForcedMostVisitedURL(&new_list, stays_the_same_2, 3000);
- AppendForcedMostVisitedURL(&new_list, new_last_forced_time, 4000);
- AppendForcedMostVisitedURL(&new_list, gets_added_1, 5000);
- AppendForcedMostVisitedURL(&new_list, move_to_forced, 6000);
- AppendMostVisitedURL(&new_list, move_to_nonforced);
- AppendMostVisitedURL(&new_list, stays_the_same_3);
- AppendMostVisitedURL(&new_list, gets_added_2);
- AppendMostVisitedURL(&new_list, gets_moved_1);
-
- history::TopSitesDelta delta;
- history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
+ AppendForcedMostVisitedURL(stays_the_same_1, 1000, &new_list);
+ AppendForcedMostVisitedURL(stays_the_same_2, 3000, &new_list);
+ AppendForcedMostVisitedURL(new_last_forced_time, 4000, &new_list);
+ AppendForcedMostVisitedURL(gets_added_1, 5000, &new_list);
+ AppendForcedMostVisitedURL(move_to_forced, 6000, &new_list);
+ AppendMostVisitedURL(move_to_nonforced, &new_list);
+ AppendMostVisitedURL(stays_the_same_3, &new_list);
+ AppendMostVisitedURL(gets_added_2, &new_list);
+ AppendMostVisitedURL(gets_moved_1, &new_list);
+
+ TopSitesDelta delta;
+ TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
ASSERT_EQ(2u, delta.added.size());
EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
@@ -496,7 +563,7 @@ TEST_F(TopSitesImplTest, SetPageThumbnail) {
GURL invalid_url("application://favicon/http://google.com/");
std::vector<MostVisitedURL> list;
- AppendMostVisitedURL(&list, url2);
+ AppendMostVisitedURL(url2, &list);
MostVisitedURL mv;
mv.url = url1b;
@@ -539,7 +606,7 @@ TEST_F(TopSitesImplTest, ThumbnailRemoved) {
// Configure top sites with 'google.com'.
std::vector<MostVisitedURL> list;
- AppendMostVisitedURL(&list, url);
+ AppendMostVisitedURL(url, &list);
SetTopSites(list);
// Create a dummy thumbnail.
@@ -740,11 +807,11 @@ TEST_F(TopSitesImplTest, SaveForcedToDB) {
// Add a number of forced URLs.
std::vector<MostVisitedURL> list;
- AppendForcedMostVisitedURL(&list, GURL("http://forced1"), 1000);
+ AppendForcedMostVisitedURL(GURL("http://forced1"), 1000, &list);
list[0].title = base::ASCIIToUTF16("forced1");
- AppendForcedMostVisitedURL(&list, GURL("http://forced2"), 2000);
- AppendForcedMostVisitedURL(&list, GURL("http://forced3"), 3000);
- AppendForcedMostVisitedURL(&list, GURL("http://forced4"), 4000);
+ AppendForcedMostVisitedURL(GURL("http://forced2"), 2000, &list);
+ AppendForcedMostVisitedURL(GURL("http://forced3"), 3000, &list);
+ AppendForcedMostVisitedURL(GURL("http://forced4"), 4000, &list);
SetTopSites(list);
// Add a thumbnail.
@@ -972,43 +1039,6 @@ TEST_F(TopSitesImplTest, DeleteNotifications) {
}
}
-// Makes sure GetUpdateDelay is updated appropriately.
-TEST_F(TopSitesImplTest, GetUpdateDelay) {
-#if defined(OS_IOS) || defined(OS_ANDROID)
- const int64_t kExpectedUpdateDelayInSecondEmpty = 30;
- const int64_t kExpectedUpdateDelayInMinute0Changed = 5;
- const int64_t kExpectedUpdateDelayInMinute3Changed = 5;
- const int64_t kExpectedUpdateDelayInMinute20Changed = 1;
-#else
- const int64_t kExpectedUpdateDelayInSecondEmpty = 30;
- const int64_t kExpectedUpdateDelayInMinute0Changed = 60;
- const int64_t kExpectedUpdateDelayInMinute3Changed = 52;
- const int64_t kExpectedUpdateDelayInMinute20Changed = 1;
-#endif
-
- SetLastNumUrlsChanged(0);
- EXPECT_EQ(kExpectedUpdateDelayInSecondEmpty, GetUpdateDelay().InSeconds());
-
- MostVisitedURLList url_list;
- url_list.resize(20);
- GURL tmp_url(GURL("http://x"));
- for (size_t i = 0; i < url_list.size(); ++i) {
- url_list[i].url = tmp_url;
- url_list[i].redirects.push_back(tmp_url);
- }
- SetTopSites(url_list);
- EXPECT_EQ(20u, last_num_urls_changed());
- SetLastNumUrlsChanged(0);
- EXPECT_EQ(kExpectedUpdateDelayInMinute0Changed, GetUpdateDelay().InMinutes());
-
- SetLastNumUrlsChanged(3);
- EXPECT_EQ(kExpectedUpdateDelayInMinute3Changed, GetUpdateDelay().InMinutes());
-
- SetLastNumUrlsChanged(20);
- EXPECT_EQ(kExpectedUpdateDelayInMinute20Changed,
- GetUpdateDelay().InMinutes());
-}
-
// Verifies that callbacks are notified correctly if requested before top sites
// has loaded.
TEST_F(TopSitesImplTest, NotifyCallbacksWhenLoaded) {
@@ -1351,59 +1381,55 @@ TEST_F(TopSitesImplTest, AddPrepopulatedPages) {
TEST_F(TopSitesImplTest, SetForcedTopSites) {
// Create forced elements in old URL list.
MostVisitedURLList old_url_list;
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/0"), 1000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/1"), 4000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/2"), 7000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/3"), 10000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/4"), 11000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/5"), 12000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/6"), 13000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/7"), 18000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/8"), 21000);
- const size_t kNumOldForcedURLs = 9;
+ AppendForcedMostVisitedURL(GURL("http://oldforced/0"), 1000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/1"), 4000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/2"), 7000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/3"), 10000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/4"), 11000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/5"), 12000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://oldforced/6"), 13000, &old_url_list);
+
+ const size_t kNumOldForcedURLs = old_url_list.size();
// Create forced elements in new URL list.
MostVisitedURLList new_url_list;
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/0"), 2000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/1"), 3000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/2"), 5000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/3"), 6000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/4"), 8000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/5"), 9000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/6"), 14000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/7"), 15000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/8"), 16000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/9"), 17000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/10"), 19000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/11"), 20000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/12"), 22000);
+ AppendForcedMostVisitedURL(GURL("http://newforced/0"), 2000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/1"), 3000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/2"), 5000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/3"), 6000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/4"), 8000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/5"), 9000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/6"), 14000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/7"), 15000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://newforced/8"), 16000, &new_url_list);
+
+ const size_t kNonForcedTopSitesCount = TopSitesImpl::kNonForcedTopSitesNumber;
+ const size_t kForcedTopSitesCount = TopSitesImpl::kForcedTopSitesNumber;
// Setup a number non-forced URLs in both old and new list.
- const size_t kNumNonForcedURLs = 20; // Maximum number of non-forced URLs.
- for (size_t i = 0; i < kNumNonForcedURLs; ++i) {
+ for (size_t i = 0; i < kNonForcedTopSitesCount; ++i) {
std::ostringstream url;
url << "http://oldnonforced/" << i;
- AppendMostVisitedURL(&old_url_list, GURL(url.str()));
+ AppendMostVisitedURL(GURL(url.str()), &old_url_list);
url.str("");
url << "http://newnonforced/" << i;
- AppendMostVisitedURL(&new_url_list, GURL(url.str()));
+ AppendMostVisitedURL(GURL(url.str()), &new_url_list);
}
// Set the initial list of URLs.
SetTopSites(old_url_list);
- EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, last_num_urls_changed());
TopSitesQuerier querier;
// Query only non-forced URLs first.
querier.QueryTopSites(top_sites(), false);
- ASSERT_EQ(kNumNonForcedURLs, querier.urls().size());
+ ASSERT_EQ(kNonForcedTopSitesCount, querier.urls().size());
// Check first URL.
EXPECT_EQ("http://oldnonforced/0", querier.urls()[0].url.spec());
// Query all URLs.
querier.QueryAllTopSites(top_sites(), false, true);
- EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, querier.urls().size());
+ EXPECT_EQ(kNumOldForcedURLs + kNonForcedTopSitesCount, querier.urls().size());
// Check first URLs.
EXPECT_EQ("http://oldforced/0", querier.urls()[0].url.spec());
@@ -1416,81 +1442,66 @@ TEST_F(TopSitesImplTest, SetForcedTopSites) {
// Query all URLs.
querier.QueryAllTopSites(top_sites(), false, true);
- // We should have reached the maximum of 20 forced URLs.
- ASSERT_EQ(20 + kNumNonForcedURLs, querier.urls().size());
+ // We should have reached the maximum of forced URLs.
+ ASSERT_EQ(kForcedTopSitesCount + kNonForcedTopSitesCount,
+ querier.urls().size());
// Check forced URLs. They follow the order of timestamps above, smaller
// timestamps since they were evicted.
- EXPECT_EQ("http://newforced/1", querier.urls()[0].url.spec());
- EXPECT_EQ(3000, querier.urls()[0].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/1", querier.urls()[1].url.spec());
- EXPECT_EQ(4000, querier.urls()[1].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/2", querier.urls()[2].url.spec());
- EXPECT_EQ(5000, querier.urls()[2].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/3", querier.urls()[3].url.spec());
- EXPECT_EQ(6000, querier.urls()[3].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/2", querier.urls()[4].url.spec());
- EXPECT_EQ(7000, querier.urls()[4].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/4", querier.urls()[5].url.spec());
- EXPECT_EQ(8000, querier.urls()[5].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/5", querier.urls()[6].url.spec());
- EXPECT_EQ(9000, querier.urls()[6].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/3", querier.urls()[7].url.spec());
- EXPECT_EQ(10000, querier.urls()[7].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/4", querier.urls()[8].url.spec());
- EXPECT_EQ(11000, querier.urls()[8].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/5", querier.urls()[9].url.spec());
- EXPECT_EQ(12000, querier.urls()[9].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/6", querier.urls()[10].url.spec());
- EXPECT_EQ(13000, querier.urls()[10].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/6", querier.urls()[11].url.spec());
- EXPECT_EQ(14000, querier.urls()[11].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/7", querier.urls()[12].url.spec());
- EXPECT_EQ(15000, querier.urls()[12].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/8", querier.urls()[13].url.spec());
- EXPECT_EQ(16000, querier.urls()[13].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/9", querier.urls()[14].url.spec());
- EXPECT_EQ(17000, querier.urls()[14].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/7", querier.urls()[15].url.spec());
- EXPECT_EQ(18000, querier.urls()[15].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/10", querier.urls()[16].url.spec());
- EXPECT_EQ(19000, querier.urls()[16].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/11", querier.urls()[17].url.spec());
- EXPECT_EQ(20000, querier.urls()[17].last_forced_time.ToJsTime());
- EXPECT_EQ("http://oldforced/8", querier.urls()[18].url.spec());
- EXPECT_EQ(21000, querier.urls()[18].last_forced_time.ToJsTime());
- EXPECT_EQ("http://newforced/12", querier.urls()[19].url.spec());
- EXPECT_EQ(22000, querier.urls()[19].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://oldforced/2", querier.urls()[0].url.spec());
+ EXPECT_EQ(7000, querier.urls()[0].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://newforced/4", querier.urls()[1].url.spec());
+ EXPECT_EQ(8000, querier.urls()[1].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://newforced/5", querier.urls()[2].url.spec());
+ EXPECT_EQ(9000, querier.urls()[2].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://oldforced/3", querier.urls()[3].url.spec());
+ EXPECT_EQ(10000, querier.urls()[3].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://oldforced/4", querier.urls()[4].url.spec());
+ EXPECT_EQ(11000, querier.urls()[4].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://oldforced/5", querier.urls()[5].url.spec());
+ EXPECT_EQ(12000, querier.urls()[5].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://oldforced/6", querier.urls()[6].url.spec());
+ EXPECT_EQ(13000, querier.urls()[6].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://newforced/6", querier.urls()[7].url.spec());
+ EXPECT_EQ(14000, querier.urls()[7].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://newforced/7", querier.urls()[8].url.spec());
+ EXPECT_EQ(15000, querier.urls()[8].last_forced_time.ToJsTime());
+ EXPECT_EQ("http://newforced/8", querier.urls()[9].url.spec());
+ EXPECT_EQ(16000, querier.urls()[9].last_forced_time.ToJsTime());
// Check first and last non-forced URLs.
- EXPECT_EQ("http://newnonforced/0", querier.urls()[20].url.spec());
- EXPECT_TRUE(querier.urls()[20].last_forced_time.is_null());
- EXPECT_EQ("http://newnonforced/19", querier.urls()[39].url.spec());
- EXPECT_TRUE(querier.urls()[39].last_forced_time.is_null());
+ EXPECT_EQ("http://newnonforced/0",
+ querier.urls()[kForcedTopSitesCount].url.spec());
+ EXPECT_TRUE(querier.urls()[kForcedTopSitesCount].last_forced_time.is_null());
+
+ size_t non_forced_end_index = querier.urls().size() - 1;
+ EXPECT_EQ("http://newnonforced/9",
+ querier.urls()[non_forced_end_index].url.spec());
+ EXPECT_TRUE(querier.urls()[non_forced_end_index].last_forced_time.is_null());
}
TEST_F(TopSitesImplTest, SetForcedTopSitesWithCollisions) {
// Setup an old URL list in order to generate some collisions.
MostVisitedURLList old_url_list;
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/0"), 1000);
+ AppendForcedMostVisitedURL(GURL("http://url/0"), 1000, &old_url_list);
// The following three will be evicted.
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/0"), 4000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/1"), 6000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/2"), 7000);
+ AppendForcedMostVisitedURL(GURL("http://collision/0"), 4000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://collision/1"), 6000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://collision/2"), 7000, &old_url_list);
// The following is evicted since all non-forced URLs are, therefore it
// doesn't cause a collision.
- AppendMostVisitedURL(&old_url_list, GURL("http://noncollision/0"));
+ AppendMostVisitedURL(GURL("http://noncollision/0"), &old_url_list);
SetTopSites(old_url_list);
// Setup a new URL list that will cause collisions.
MostVisitedURLList new_url_list;
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/1"), 2000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://url/2"), 3000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/0"), 5000);
- AppendForcedMostVisitedURL(&new_url_list, GURL("http://noncollision/0"),
- 9000);
- AppendMostVisitedURL(&new_url_list, GURL("http://collision/2"));
- AppendMostVisitedURL(&new_url_list, GURL("http://url/3"));
+ AppendForcedMostVisitedURL(GURL("http://collision/1"), 2000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://url/2"), 3000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://collision/0"), 5000, &new_url_list);
+ AppendForcedMostVisitedURL(GURL("http://noncollision/0"), 9000,
+ &new_url_list);
+ AppendMostVisitedURL(GURL("http://collision/2"), &new_url_list);
+ AppendMostVisitedURL(GURL("http://url/3"), &new_url_list);
SetTopSites(new_url_list);
// Query all URLs.
@@ -1519,9 +1530,9 @@ TEST_F(TopSitesImplTest, SetForcedTopSitesWithCollisions) {
TEST_F(TopSitesImplTest, SetTopSitesIdentical) {
// Set the initial list of URLs.
MostVisitedURLList url_list;
- AppendForcedMostVisitedURL(&url_list, GURL("http://url/0"), 1000);
- AppendMostVisitedURL(&url_list, GURL("http://url/1"));
- AppendMostVisitedURL(&url_list, GURL("http://url/2"));
+ AppendForcedMostVisitedURL(GURL("http://url/0"), 1000, &url_list);
+ AppendMostVisitedURL(GURL("http://url/1"), &url_list);
+ AppendMostVisitedURL(GURL("http://url/2"), &url_list);
SetTopSites(url_list);
// Set the new list of URLs to be exactly the same.
@@ -1543,15 +1554,15 @@ TEST_F(TopSitesImplTest, SetTopSitesIdentical) {
TEST_F(TopSitesImplTest, SetTopSitesWithAlreadyExistingForcedURLs) {
// Set the initial list of URLs.
MostVisitedURLList old_url_list;
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/0/redir"), 1000);
- AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/1"), 2000);
+ AppendForcedMostVisitedURL(GURL("http://url/0/redir"), 1000, &old_url_list);
+ AppendForcedMostVisitedURL(GURL("http://url/1"), 2000, &old_url_list);
SetTopSites(old_url_list);
// Setup a new URL list that will cause collisions.
MostVisitedURLList new_url_list;
- AppendMostVisitedURLWithRedirect(&new_url_list, GURL("http://url/0/redir"),
- GURL("http://url/0"));
- AppendMostVisitedURL(&new_url_list, GURL("http://url/1"));
+ AppendMostVisitedURLWithRedirect(GURL("http://url/0/redir"),
+ GURL("http://url/0"), &new_url_list);
+ AppendMostVisitedURL(GURL("http://url/1"), &new_url_list);
SetTopSites(new_url_list);
// Query all URLs.
@@ -1571,11 +1582,11 @@ TEST_F(TopSitesImplTest, SetTopSitesWithAlreadyExistingForcedURLs) {
TEST_F(TopSitesImplTest, AddForcedURL) {
// Set the initial list of URLs.
MostVisitedURLList url_list;
- AppendForcedMostVisitedURL(&url_list, GURL("http://forced/0"), 2000);
- AppendForcedMostVisitedURL(&url_list, GURL("http://forced/1"), 4000);
- AppendMostVisitedURL(&url_list, GURL("http://nonforced/0"));
- AppendMostVisitedURL(&url_list, GURL("http://nonforced/1"));
- AppendMostVisitedURL(&url_list, GURL("http://nonforced/2"));
+ AppendForcedMostVisitedURL(GURL("http://forced/0"), 2000, &url_list);
+ AppendForcedMostVisitedURL(GURL("http://forced/1"), 4000, &url_list);
+ AppendMostVisitedURL(GURL("http://nonforced/0"), &url_list);
+ AppendMostVisitedURL(GURL("http://nonforced/1"), &url_list);
+ AppendMostVisitedURL(GURL("http://nonforced/2"), &url_list);
SetTopSites(url_list);
// Add forced sites here and there to exercise a couple of cases.
diff --git a/chromium/components/history/core/browser/typed_url_data_type_controller.cc b/chromium/components/history/core/browser/typed_url_data_type_controller.cc
index d27a4f61a7e..2fc2c86ab21 100644
--- a/chromium/components/history/core/browser/typed_url_data_type_controller.cc
+++ b/chromium/components/history/core/browser/typed_url_data_type_controller.cc
@@ -91,7 +91,7 @@ void TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged() {
}
bool TypedUrlDataTypeController::PostTaskOnModelThread(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const base::Closure& task) {
DCHECK(CalledOnValidThread());
history::HistoryService* history = sync_client_->GetHistoryService();
diff --git a/chromium/components/history/core/browser/typed_url_data_type_controller.h b/chromium/components/history/core/browser/typed_url_data_type_controller.h
index 2f5e1d06bc7..1883652170d 100644
--- a/chromium/components/history/core/browser/typed_url_data_type_controller.h
+++ b/chromium/components/history/core/browser/typed_url_data_type_controller.h
@@ -30,7 +30,7 @@ class TypedUrlDataTypeController : public syncer::AsyncDirectoryTypeController {
protected:
// AsyncDirectoryTypeController implementation.
- bool PostTaskOnModelThread(const tracked_objects::Location& from_here,
+ bool PostTaskOnModelThread(const base::Location& from_here,
const base::Closure& task) override;
private:
diff --git a/chromium/components/history/core/browser/typed_url_model_type_controller.cc b/chromium/components/history/core/browser/typed_url_model_type_controller.cc
new file mode 100644
index 00000000000..38d45165f95
--- /dev/null
+++ b/chromium/components/history/core/browser/typed_url_model_type_controller.cc
@@ -0,0 +1,108 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/history/core/browser/typed_url_model_type_controller.h"
+
+#include "base/bind.h"
+#include "components/history/core/browser/history_db_task.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync/driver/sync_client.h"
+
+using syncer::ModelType;
+using syncer::ModelTypeController;
+using syncer::ModelTypeSyncBridge;
+using syncer::SyncClient;
+
+namespace history {
+
+namespace {
+
+// The history service exposes a special non-standard task API which calls back
+// once a task has been dispatched, so we have to build a special wrapper around
+// the tasks we want to run.
+class RunTaskOnHistoryThread : public HistoryDBTask {
+ public:
+ explicit RunTaskOnHistoryThread(const base::Closure& task) : task_(task) {}
+
+ bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) override {
+ // Invoke the task, then free it immediately so we don't keep a reference
+ // around all the way until DoneRunOnMainThread() is invoked back on the
+ // main thread - we want to release references as soon as possible to avoid
+ // keeping them around too long during shutdown.
+ task_.Run();
+ task_.Reset();
+ return true;
+ }
+
+ void DoneRunOnMainThread() override {}
+
+ protected:
+ base::Closure task_;
+};
+
+} // namespace
+
+TypedURLModelTypeController::TypedURLModelTypeController(
+ SyncClient* sync_client,
+ const char* history_disabled_pref_name)
+ : ModelTypeController(syncer::TYPED_URLS, sync_client, nullptr),
+ history_disabled_pref_name_(history_disabled_pref_name) {
+ pref_registrar_.Init(sync_client->GetPrefService());
+ pref_registrar_.Add(
+ history_disabled_pref_name_,
+ base::Bind(
+ &TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged,
+ base::AsWeakPtr(this)));
+}
+
+TypedURLModelTypeController::~TypedURLModelTypeController() {}
+
+bool TypedURLModelTypeController::ReadyForStart() const {
+ return !sync_client()->GetPrefService()->GetBoolean(
+ history_disabled_pref_name_);
+}
+
+void TypedURLModelTypeController::PostBridgeTask(const base::Location& location,
+ const BridgeTask& task) {
+ history::HistoryService* history = sync_client()->GetHistoryService();
+ if (!history) {
+ // History must be disabled - don't start.
+ LOG(WARNING) << "Cannot access history service.";
+ return;
+ }
+
+ TypedURLSyncBridge* bridge = history->GetTypedURLSyncBridge();
+ PostTaskOnHistoryThread(base::Bind(task, bridge));
+}
+
+void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
+ if (sync_client()->GetPrefService()->GetBoolean(
+ history_disabled_pref_name_)) {
+ // We've turned off history persistence, so if we are running,
+ // generate an unrecoverable error. This can be fixed by restarting
+ // Chrome (on restart, typed urls will not be a registered type).
+ if (state() != NOT_RUNNING && state() != STOPPING) {
+ PostTaskOnHistoryThread(base::Bind(
+ &TypedURLModelTypeController::ReportModelError, base::AsWeakPtr(this),
+ syncer::ModelError(FROM_HERE,
+ "History saving is now disabled by policy.")));
+ }
+ }
+}
+
+void TypedURLModelTypeController::PostTaskOnHistoryThread(
+ const base::Closure& task) {
+ history::HistoryService* history = sync_client()->GetHistoryService();
+ if (!history) {
+ // History must be disabled - don't start.
+ LOG(WARNING) << "Cannot access history service.";
+ return;
+ }
+
+ history->ScheduleDBTask(std::make_unique<RunTaskOnHistoryThread>(task),
+ &task_tracker_);
+}
+
+} // namespace history
diff --git a/chromium/components/history/core/browser/typed_url_model_type_controller.h b/chromium/components/history/core/browser/typed_url_model_type_controller.h
new file mode 100644
index 00000000000..77e4f460c6e
--- /dev/null
+++ b/chromium/components/history/core/browser/typed_url_model_type_controller.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
+#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
+
+#include "base/task/cancelable_task_tracker.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "components/sync/driver/model_type_controller.h"
+
+namespace history {
+
+class TypedURLModelTypeController : public syncer::ModelTypeController {
+ public:
+ TypedURLModelTypeController(syncer::SyncClient* sync_client,
+ const char* history_disabled_pref_name);
+
+ ~TypedURLModelTypeController() override;
+
+ // syncer::DataTypeController implementation.
+ bool ReadyForStart() const override;
+
+ private:
+ // syncer::ModelTypeController implementation.
+ void PostBridgeTask(const base::Location& location,
+ const BridgeTask& task) override;
+
+ void OnSavingBrowserHistoryDisabledChanged();
+
+ void PostTaskOnHistoryThread(const base::Closure& task);
+
+ // Name of the pref that indicates whether saving history is disabled.
+ const char* history_disabled_pref_name_;
+
+ PrefChangeRegistrar pref_registrar_;
+
+ // Helper object to make sure we don't leave tasks running on the history
+ // thread.
+ base::CancelableTaskTracker task_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TypedURLModelTypeController);
+};
+
+} // namespace history
+
+#endif // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
diff --git a/chromium/components/history/core/browser/typed_url_sync_bridge.cc b/chromium/components/history/core/browser/typed_url_sync_bridge.cc
index 9a437f71686..c81a656f92d 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge.cc
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge.cc
@@ -4,6 +4,7 @@
#include "components/history/core/browser/typed_url_sync_bridge.h"
+#include "base/auto_reset.h"
#include "base/big_endian.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -82,6 +83,7 @@ TypedURLSyncBridge::TypedURLSyncBridge(
const ChangeProcessorFactory& change_processor_factory)
: ModelTypeSyncBridge(change_processor_factory, syncer::TYPED_URLS),
history_backend_(history_backend),
+ processing_syncer_changes_(false),
sync_metadata_database_(sync_metadata_database),
num_db_accesses_(0),
num_db_errors_(0),
@@ -136,13 +138,12 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
// Ignore old sync urls that don't have any transition data stored with
// them, or transition data that does not match the visit data (will be
- // deleted below).
+ // deleted later by GarbageCollectionDirective).
if (specifics.visit_transitions_size() == 0 ||
specifics.visit_transitions_size() != specifics.visits_size()) {
- // Generate a debug assertion to help track down http://crbug.com/91473,
- // even though we gracefully handle this case by overwriting this node.
DCHECK_EQ(specifics.visits_size(), specifics.visit_transitions_size());
- DVLOG(1) << "Ignoring obsolete sync url with no visit transition info.";
+ DLOG(WARNING)
+ << "Ignoring obsolete sync url with no visit transition info.";
continue;
}
@@ -151,17 +152,13 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
&updated_synced_urls);
}
- for (const auto& kv : new_db_urls) {
- SendTypedURLToProcessor(kv.second, local_visit_vectors[kv.first],
- metadata_change_list.get());
- }
-
base::Optional<ModelError> error = WriteToHistoryBackend(
&new_synced_urls, &updated_synced_urls, NULL, &new_synced_visits, NULL);
-
if (error)
return error;
+ // Update storage key here first, and then send updated typed URL to sync
+ // below, otherwise processor will have duplicate entries.
for (const EntityChange& entity_change : entity_data) {
DCHECK(entity_change.data().specifics.has_typed_url());
std::string storage_key =
@@ -175,6 +172,12 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
}
}
+ // Send new/updated typed URL to sync.
+ for (const auto& kv : new_db_urls) {
+ SendTypedURLToProcessor(kv.second, local_visit_vectors[kv.first],
+ metadata_change_list.get());
+ }
+
UMA_HISTOGRAM_PERCENTAGE("Sync.TypedUrlMergeAndStartSyncingErrors",
GetErrorPercentage());
ClearErrorStats();
@@ -229,9 +232,11 @@ base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
&updated_synced_urls, &new_synced_urls);
}
- WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls,
- &pending_deleted_urls, &new_synced_visits,
- &deleted_visits);
+ base::Optional<ModelError> error = WriteToHistoryBackend(
+ &new_synced_urls, &updated_synced_urls, &pending_deleted_urls,
+ &new_synced_visits, &deleted_visits);
+ if (error)
+ return error;
// New entities were either ignored or written to history DB and assigned a
// storage key. Notify processor about updated storage keys.
@@ -249,7 +254,9 @@ base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
}
}
- return {};
+ return static_cast<syncer::SyncMetadataStoreChangeList*>(
+ metadata_change_list.get())
+ ->TakeError();
}
void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
@@ -343,6 +350,9 @@ void TypedURLSyncBridge::OnURLVisited(HistoryBackend* history_backend,
base::Time visit_time) {
DCHECK(sequence_checker_.CalledOnValidSequence());
+ if (processing_syncer_changes_)
+ return; // These are changes originating from us, ignore.
+
if (!change_processor()->IsTrackingMetadata())
return; // Sync processor not yet ready, don't sync.
if (!ShouldSyncVisit(row.typed_count(), transition))
@@ -358,6 +368,9 @@ void TypedURLSyncBridge::OnURLsModified(HistoryBackend* history_backend,
const URLRows& changed_urls) {
DCHECK(sequence_checker_.CalledOnValidSequence());
+ if (processing_syncer_changes_)
+ return; // These are changes originating from us, ignore.
+
if (!change_processor()->IsTrackingMetadata())
return; // Sync processor not yet ready, don't sync.
@@ -380,6 +393,10 @@ void TypedURLSyncBridge::OnURLsDeleted(HistoryBackend* history_backend,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) {
DCHECK(sequence_checker_.CalledOnValidSequence());
+
+ if (processing_syncer_changes_)
+ return; // These are changes originating from us, ignore.
+
if (!change_processor()->IsTrackingMetadata())
return; // Sync processor not yet ready, don't sync.
@@ -912,6 +929,10 @@ base::Optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend(
const std::vector<GURL>* deleted_urls,
const TypedURLVisitVector* new_visits,
const VisitVector* deleted_visits) {
+ DCHECK_EQ(processing_syncer_changes_, false);
+ // Set flag to stop accepting history change notifications from backend.
+ base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
+
if (deleted_urls && !deleted_urls->empty())
history_backend_->DeleteURLs(*deleted_urls);
diff --git a/chromium/components/history/core/browser/typed_url_sync_bridge.h b/chromium/components/history/core/browser/typed_url_sync_bridge.h
index 01f25ee19b3..cb92a96ff0f 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge.h
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge.h
@@ -217,6 +217,10 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// and sync changes to.
HistoryBackend* const history_backend_;
+ // Whether we're currently processing changes from the syncer. While this is
+ // true, we ignore any local url changes, since we triggered them.
+ bool processing_syncer_changes_;
+
// A non-owning pointer to the database, which is for storing typed urls sync
// metadata and state.
TypedURLSyncMetadataDatabase* const sync_metadata_database_;
diff --git a/chromium/components/history/core/browser/typed_url_syncable_service.cc b/chromium/components/history/core/browser/typed_url_syncable_service.cc
index 3f357843574..98bf4b9ac3a 100644
--- a/chromium/components/history/core/browser/typed_url_syncable_service.cc
+++ b/chromium/components/history/core/browser/typed_url_syncable_service.cc
@@ -233,7 +233,7 @@ syncer::SyncDataList TypedUrlSyncableService::GetAllSyncData(
}
syncer::SyncError TypedUrlSyncableService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
DCHECK(sequence_checker_.CalledOnValidSequence());
diff --git a/chromium/components/history/core/browser/typed_url_syncable_service.h b/chromium/components/history/core/browser/typed_url_syncable_service.h
index 39f2fd53da9..9cad7f2acd5 100644
--- a/chromium/components/history/core/browser/typed_url_syncable_service.h
+++ b/chromium/components/history/core/browser/typed_url_syncable_service.h
@@ -51,7 +51,7 @@ class TypedUrlSyncableService : public syncer::SyncableService,
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// history::HistoryBackendObserver:
diff --git a/chromium/components/history/core/browser/url_database.cc b/chromium/components/history/core/browser/url_database.cc
index 4d8c5df4172..5fb9762943c 100644
--- a/chromium/components/history/core/browser/url_database.cc
+++ b/chromium/components/history/core/browser/url_database.cc
@@ -60,7 +60,7 @@ std::string URLDatabase::GURLToDatabaseURL(const GURL& gurl) {
// Convenience to fill a URLRow. Must be in sync with the fields in
// kURLRowFields.
-void URLDatabase::FillURLRow(sql::Statement& s, URLRow* i) {
+void URLDatabase::FillURLRow(const sql::Statement& s, URLRow* i) {
DCHECK(i);
i->set_id(s.ColumnInt64(0));
i->set_url(GURL(s.ColumnString(1)));
@@ -87,18 +87,6 @@ bool URLDatabase::GetURLRow(URLID url_id, URLRow* info) {
return false;
}
-bool URLDatabase::GetAllTypedUrls(URLRows* urls) {
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE typed_count > 0"));
-
- while (statement.Step()) {
- URLRow info;
- FillURLRow(statement, &info);
- urls->push_back(info);
- }
- return true;
-}
-
URLID URLDatabase::GetRowForURL(const GURL& url, URLRow* info) {
sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
"SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE url=?"));
@@ -165,6 +153,27 @@ URLID URLDatabase::AddURLInternal(const URLRow& info, bool is_temporary) {
return GetDB().GetLastInsertRowId();
}
+bool URLDatabase::URLTableContainsAutoincrement() {
+ // sqlite_master has columns:
+ // type - "index" or "table".
+ // name - name of created element.
+ // tbl_name - name of element, or target table in case of index.
+ // rootpage - root page of the element in database file.
+ // sql - SQL to create the element.
+ sql::Statement statement(GetDB().GetUniqueStatement(
+ "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'urls'"));
+
+ // urls table does not exist.
+ if (!statement.Step())
+ return false;
+
+ std::string urls_schema = statement.ColumnString(0);
+ // We check if the whole schema contains "AUTOINCREMENT", since
+ // "AUTOINCREMENT" only can be used for "INTEGER PRIMARY KEY", so we assume no
+ // other columns could cantain "AUTOINCREMENT".
+ return urls_schema.find("AUTOINCREMENT") != std::string::npos;
+}
+
bool URLDatabase::InsertOrUpdateURLRowByID(const URLRow& info) {
// SQLite does not support INSERT OR UPDATE, however, it does have INSERT OR
// REPLACE, which is feasible to use, because of the following.
@@ -227,9 +236,7 @@ bool URLDatabase::CommitTemporaryURLTable() {
// Re-create the index over the now permanent URLs table -- this was not there
// for the temporary table.
- CreateMainURLIndex();
-
- return true;
+ return CreateMainURLIndex();
}
bool URLDatabase::InitURLEnumeratorForEverything(URLEnumerator* enumerator) {
@@ -639,9 +646,7 @@ bool URLDatabase::RecreateURLTableWithAllContents() {
}
// Rename/commit the tmp table.
- CommitTemporaryURLTable();
-
- return true;
+ return CommitTemporaryURLTable();
}
const int kLowQualityMatchTypedLimit = 1;
diff --git a/chromium/components/history/core/browser/url_database.h b/chromium/components/history/core/browser/url_database.h
index 087e7864d68..dd8f2feff7a 100644
--- a/chromium/components/history/core/browser/url_database.h
+++ b/chromium/components/history/core/browser/url_database.h
@@ -7,6 +7,9 @@
#include <stddef.h>
+#include <string>
+#include <vector>
+
#include "base/macros.h"
#include "components/history/core/browser/keyword_id.h"
#include "components/history/core/browser/url_row.h"
@@ -59,10 +62,6 @@ class URLDatabase {
// success and false otherwise.
bool GetURLRow(URLID url_id, URLRow* info);
- // Looks up all urls that were typed in manually. Fills info with the data.
- // Returns true on success and false otherwise.
- bool GetAllTypedUrls(URLRows* urls);
-
// Looks up the given URL and if it exists, fills the given pointers with the
// associated info and returns the ID of that URL. If the info pointer is
// NULL, no information about the URL will be filled in, only the ID will be
@@ -286,9 +285,13 @@ class URLDatabase {
// be used in between CreateTemporaryURLTable() and CommitTemporaryURLTable().
URLID AddURLInternal(const URLRow& info, bool is_temporary);
+ // Return ture if the urls table's schema contains "AUTOINCREMENT".
+ // false if table do not contain AUTOINCREMENT, or the table is not created.
+ bool URLTableContainsAutoincrement();
+
// Convenience to fill a URLRow. Must be in sync with the fields in
// kHistoryURLRowFields.
- static void FillURLRow(sql::Statement& s, URLRow* i);
+ static void FillURLRow(const sql::Statement& s, URLRow* i);
// Returns the database for the functions in this interface. The decendent of
// this class implements these functions to return its objects.
diff --git a/chromium/components/history/core/browser/url_database_unittest.cc b/chromium/components/history/core/browser/url_database_unittest.cc
index 5b5c33c1a63..76692a116a4 100644
--- a/chromium/components/history/core/browser/url_database_unittest.cc
+++ b/chromium/components/history/core/browser/url_database_unittest.cc
@@ -459,4 +459,13 @@ TEST_F(URLDatabaseTest, MigrationURLTableForAddingAUTOINCREMENT) {
EXPECT_NE(info4.id(), info5.id());
}
+TEST_F(URLDatabaseTest, URLTableContainsAUTOINCREMENTTest) {
+ CreateVersion33URLTable();
+ EXPECT_FALSE(URLTableContainsAutoincrement());
+
+ // Upgrade urls table.
+ RecreateURLTableWithAllContents();
+ EXPECT_TRUE(URLTableContainsAutoincrement());
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/url_row.h b/chromium/components/history/core/browser/url_row.h
index 64f00dabec0..907ad2a1bf8 100644
--- a/chromium/components/history/core/browser/url_row.h
+++ b/chromium/components/history/core/browser/url_row.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <vector>
+
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "components/query_parser/snippet.h"
diff --git a/chromium/components/history/core/browser/visit_database.cc b/chromium/components/history/core/browser/visit_database.cc
index 3d998852472..0ef84afb008 100644
--- a/chromium/components/history/core/browser/visit_database.cc
+++ b/chromium/components/history/core/browser/visit_database.cc
@@ -11,6 +11,8 @@
#include <limits>
#include <map>
#include <set>
+#include <string>
+#include <utility>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
@@ -30,16 +32,17 @@ VisitDatabase::~VisitDatabase() {
bool VisitDatabase::InitVisitTable() {
if (!GetDB().DoesTableExist("visits")) {
- if (!GetDB().Execute("CREATE TABLE visits("
- "id INTEGER PRIMARY KEY,"
- "url INTEGER NOT NULL," // key of the URL this corresponds to
- "visit_time INTEGER NOT NULL,"
- "from_visit INTEGER,"
- "transition INTEGER DEFAULT 0 NOT NULL,"
- "segment_id INTEGER,"
- // Some old DBs may have an "is_indexed" field here, but this is no
- // longer used and should NOT be read or written from any longer.
- "visit_duration INTEGER DEFAULT 0 NOT NULL)"))
+ if (!GetDB().Execute(
+ "CREATE TABLE visits("
+ "id INTEGER PRIMARY KEY,"
+ "url INTEGER NOT NULL," // key of the URL this corresponds to
+ "visit_time INTEGER NOT NULL,"
+ "from_visit INTEGER,"
+ "transition INTEGER DEFAULT 0 NOT NULL,"
+ "segment_id INTEGER,"
+ // Some old DBs may have an "is_indexed" field here, but this is no
+ // longer used and should NOT be read or written from any longer.
+ "visit_duration INTEGER DEFAULT 0 NOT NULL)"))
return false;
}
@@ -85,7 +88,8 @@ bool VisitDatabase::DropVisitTable() {
// Must be in sync with HISTORY_VISIT_ROW_FIELDS.
// static
-void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) {
+void VisitDatabase::FillVisitRow(const sql::Statement& statement,
+ VisitRow* visit) {
visit->visit_id = statement.ColumnInt64(0);
visit->url_id = statement.ColumnInt64(1);
visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2));
@@ -349,6 +353,22 @@ bool VisitDatabase::GetVisitsInRangeForTransition(
return FillVisitVector(statement, visits);
}
+bool VisitDatabase::GetAllURLIDsForTransition(ui::PageTransition transition,
+ std::vector<URLID>* urls) {
+ DCHECK(urls);
+ urls->clear();
+ sql::Statement statement(
+ GetDB().GetUniqueStatement("SELECT DISTINCT url FROM visits "
+ "WHERE (transition & ?) == ?"));
+ statement.BindInt(0, ui::PAGE_TRANSITION_CORE_MASK);
+ statement.BindInt(1, transition);
+
+ while (statement.Step()) {
+ urls->push_back(statement.ColumnInt64(0));
+ }
+ return statement.Succeeded();
+}
+
bool VisitDatabase::GetVisibleVisitsInRange(const QueryOptions& options,
VisitVector* visits) {
visits->clear();
diff --git a/chromium/components/history/core/browser/visit_database.h b/chromium/components/history/core/browser/visit_database.h
index 1bb743a8a02..ee950544f97 100644
--- a/chromium/components/history/core/browser/visit_database.h
+++ b/chromium/components/history/core/browser/visit_database.h
@@ -102,6 +102,11 @@ class VisitDatabase {
ui::PageTransition transition,
VisitVector* visits);
+ // Looks up URLIDs for all visits with specified transition. Returns true on
+ // success and false otherwise.
+ bool GetAllURLIDsForTransition(ui::PageTransition transition,
+ std::vector<URLID>* urls);
+
// Fills all visits in the given time range into the given vector that should
// be user-visible, which excludes things like redirects and subframes. The
// begin time is inclusive, the end time is exclusive. Either time can be
@@ -193,7 +198,7 @@ class VisitDatabase {
// Convenience to fill a VisitRow. Assumes the visit values are bound starting
// at index 0.
- static void FillVisitRow(sql::Statement& statement, VisitRow* visit);
+ static void FillVisitRow(const sql::Statement& statement, VisitRow* visit);
// Convenience to fill a VisitVector. Assumes that statement.step()
// hasn't happened yet.
diff --git a/chromium/components/history/core/browser/visit_database_unittest.cc b/chromium/components/history/core/browser/visit_database_unittest.cc
index 77218eff842..77be2f6388d 100644
--- a/chromium/components/history/core/browser/visit_database_unittest.cc
+++ b/chromium/components/history/core/browser/visit_database_unittest.cc
@@ -353,6 +353,18 @@ TEST_F(VisitDatabaseTest, GetVisibleVisitsInRange) {
EXPECT_TRUE(IsVisitInfoEqual(results[0], test_visit_rows[1]));
}
+TEST_F(VisitDatabaseTest, GetAllURLIDsForTransition) {
+ std::vector<VisitRow> test_visit_rows = GetTestVisitRows();
+
+ for (size_t i = 0; i < test_visit_rows.size(); ++i) {
+ EXPECT_TRUE(AddVisit(&test_visit_rows[i], SOURCE_BROWSED));
+ }
+ std::vector<URLID> url_ids;
+ GetAllURLIDsForTransition(ui::PAGE_TRANSITION_TYPED, &url_ids);
+ EXPECT_EQ(1U, url_ids.size());
+ EXPECT_EQ(test_visit_rows[0].url_id, url_ids[0]);
+}
+
TEST_F(VisitDatabaseTest, VisitSource) {
// Add visits.
VisitRow visit_info1(111, Time::Now(), 0, ui::PAGE_TRANSITION_LINK, 0);