summaryrefslogtreecommitdiff
path: root/chromium/components/history
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/components/history
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
downloadqtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/history')
-rw-r--r--chromium/components/history/content/browser/download_conversions.cc4
-rw-r--r--chromium/components/history/core/browser/BUILD.gn5
-rw-r--r--chromium/components/history/core/browser/DEPS1
-rw-r--r--chromium/components/history/core/browser/android/visit_sql_handler.cc2
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.cc8
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.h5
-rw-r--r--chromium/components/history/core/browser/delete_directive_handler.cc2
-rw-r--r--chromium/components/history/core/browser/domain_mixing_metrics.cc150
-rw-r--r--chromium/components/history/core/browser/domain_mixing_metrics.h35
-rw-r--r--chromium/components/history/core/browser/domain_mixing_metrics_unittest.cc89
-rw-r--r--chromium/components/history/core/browser/download_constants.h1
-rw-r--r--chromium/components/history/core/browser/download_types.cc3
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.cc80
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.h17
-rw-r--r--chromium/components/history/core/browser/expire_history_backend_unittest.cc82
-rw-r--r--chromium/components/history/core/browser/history_backend.cc93
-rw-r--r--chromium/components/history/core/browser/history_backend.h17
-rw-r--r--chromium/components/history/core/browser/history_backend_db_unittest.cc115
-rw-r--r--chromium/components/history/core/browser/history_backend_notifier.h14
-rw-r--r--chromium/components/history/core/browser/history_backend_unittest.cc59
-rw-r--r--chromium/components/history/core/browser/history_constants.cc2
-rw-r--r--chromium/components/history/core/browser/history_constants.h5
-rw-r--r--chromium/components/history/core/browser/history_database.cc9
-rw-r--r--chromium/components/history/core/browser/history_database_params.cc5
-rw-r--r--chromium/components/history/core/browser/history_model_worker.cc4
-rw-r--r--chromium/components/history/core/browser/history_querying_unittest.cc2
-rw-r--r--chromium/components/history/core/browser/history_service.cc47
-rw-r--r--chromium/components/history/core/browser/history_service.h20
-rw-r--r--chromium/components/history/core/browser/history_service_observer.h31
-rw-r--r--chromium/components/history/core/browser/history_service_unittest.cc5
-rw-r--r--chromium/components/history/core/browser/history_types.cc46
-rw-r--r--chromium/components/history/core/browser/history_types.h98
-rw-r--r--chromium/components/history/core/browser/in_memory_database.cc3
-rw-r--r--chromium/components/history/core/browser/in_memory_history_backend.cc9
-rw-r--r--chromium/components/history/core/browser/in_memory_history_backend.h5
-rw-r--r--chromium/components/history/core/browser/thumbnail_database_unittest.cc12
-rw-r--r--chromium/components/history/core/browser/top_sites.cc3
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.cc9
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.h5
-rw-r--r--chromium/components/history/core/browser/typed_url_model_type_controller.cc21
-rw-r--r--chromium/components/history/core/browser/typed_url_model_type_controller.h2
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge.cc32
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc136
-rw-r--r--chromium/components/history/core/browser/visit_database.cc106
-rw-r--r--chromium/components/history/core/browser/visit_database.h18
-rw-r--r--chromium/components/history/core/browser/visit_database_unittest.cc224
-rw-r--r--chromium/components/history/core/browser/web_history_service.cc2
47 files changed, 1232 insertions, 411 deletions
diff --git a/chromium/components/history/content/browser/download_conversions.cc b/chromium/components/history/content/browser/download_conversions.cc
index 3a6fd5c21a5..60dc386d973 100644
--- a/chromium/components/history/content/browser/download_conversions.cc
+++ b/chromium/components/history/content/browser/download_conversions.cc
@@ -69,6 +69,8 @@ download::DownloadDangerType ToContentDownloadDangerType(
return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
case DownloadDangerType::POTENTIALLY_UNWANTED:
return download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
+ case DownloadDangerType::WHITELISTED_BY_POLICY:
+ return download::DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY;
case DownloadDangerType::INVALID:
NOTREACHED();
return download::DOWNLOAD_DANGER_TYPE_MAX;
@@ -98,6 +100,8 @@ DownloadDangerType ToHistoryDownloadDangerType(
return DownloadDangerType::DANGEROUS_HOST;
case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
return DownloadDangerType::POTENTIALLY_UNWANTED;
+ case download::DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY:
+ return DownloadDangerType::WHITELISTED_BY_POLICY;
default:
NOTREACHED();
return DownloadDangerType::INVALID;
diff --git a/chromium/components/history/core/browser/BUILD.gn b/chromium/components/history/core/browser/BUILD.gn
index d3a9b446dbd..10fd62ac60e 100644
--- a/chromium/components/history/core/browser/BUILD.gn
+++ b/chromium/components/history/core/browser/BUILD.gn
@@ -11,6 +11,8 @@ static_library("browser") {
"default_top_sites_provider.h",
"delete_directive_handler.cc",
"delete_directive_handler.h",
+ "domain_mixing_metrics.cc",
+ "domain_mixing_metrics.h",
"download_constants.h",
"download_database.cc",
"download_database.h",
@@ -103,6 +105,7 @@ static_library("browser") {
"//base:i18n",
"//components/data_use_measurement/core",
"//components/favicon_base",
+ "//components/google/core/browser",
"//components/history/core/common",
"//components/keyed_service/core",
"//components/prefs",
@@ -171,6 +174,7 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/history/history.31.sql",
"//components/test/data/history/history.32.sql",
"//components/test/data/history/history.38.sql",
+ "//components/test/data/history/history.39.sql",
"//components/test/data/history/thumbnail_wild/Favicons.corrupt_meta.disable",
"//components/test/data/history/thumbnail_wild/Favicons.v2.init.sql",
"//components/test/data/history/thumbnail_wild/Favicons.v3.init.sql",
@@ -191,6 +195,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"browsing_history_service_unittest.cc",
+ "domain_mixing_metrics_unittest.cc",
"download_slice_info_unittest.cc",
"expire_history_backend_unittest.cc",
"history_backend_db_unittest.cc",
diff --git a/chromium/components/history/core/browser/DEPS b/chromium/components/history/core/browser/DEPS
index d8117751610..26e3a1cc0b1 100644
--- a/chromium/components/history/core/browser/DEPS
+++ b/chromium/components/history/core/browser/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/data_use_measurement/core",
+ "+components/google/core/browser/google_util.h",
"+components/variations",
"+services/identity/public",
]
diff --git a/chromium/components/history/core/browser/android/visit_sql_handler.cc b/chromium/components/history/core/browser/android/visit_sql_handler.cc
index 97222dd4339..5af06e70487 100644
--- a/chromium/components/history/core/browser/android/visit_sql_handler.cc
+++ b/chromium/components/history/core/browser/android/visit_sql_handler.cc
@@ -121,7 +121,7 @@ bool VisitSQLHandler::AddVisit(URLID url_id, const Time& visit_time) {
// TODO : Is 'ui::PAGE_TRANSITION_AUTO_BOOKMARK' proper?
// if not, a new ui::PageTransition type will need.
VisitRow visit_row(url_id, visit_time, 0,
- ui::PAGE_TRANSITION_AUTO_BOOKMARK, 0);
+ ui::PAGE_TRANSITION_AUTO_BOOKMARK, 0, false);
return visit_db_->AddVisit(&visit_row, SOURCE_BROWSED);
}
diff --git a/chromium/components/history/core/browser/browsing_history_service.cc b/chromium/components/history/core/browser/browsing_history_service.cc
index fbb4f4a9c7e..153dad43e1d 100644
--- a/chromium/components/history/core/browser/browsing_history_service.cc
+++ b/chromium/components/history/core/browser/browsing_history_service.cc
@@ -742,11 +742,9 @@ static bool DeletionsDiffer(const URLRows& deleted_rows,
}
void BrowsingHistoryService::OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
- if (all_history || DeletionsDiffer(deleted_rows, urls_to_be_deleted_))
+ const DeletionInfo& deletion_info) {
+ if (deletion_info.IsAllHistory() ||
+ DeletionsDiffer(deletion_info.deleted_rows(), urls_to_be_deleted_))
driver_->HistoryDeleted();
}
diff --git a/chromium/components/history/core/browser/browsing_history_service.h b/chromium/components/history/core/browser/browsing_history_service.h
index 41d15e9dae2..b768c8a4744 100644
--- a/chromium/components/history/core/browser/browsing_history_service.h
+++ b/chromium/components/history/core/browser/browsing_history_service.h
@@ -202,10 +202,7 @@ class BrowsingHistoryService : public HistoryServiceObserver,
// HistoryServiceObserver implementation.
void OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override;
+ const DeletionInfo& deletion_info) override;
// WebHistoryServiceObserver implementation.
void OnWebHistoryDeleted() override;
diff --git a/chromium/components/history/core/browser/delete_directive_handler.cc b/chromium/components/history/core/browser/delete_directive_handler.cc
index de730f6de8b..a0b737bb02b 100644
--- a/chromium/components/history/core/browser/delete_directive_handler.cc
+++ b/chromium/components/history/core/browser/delete_directive_handler.cc
@@ -178,7 +178,7 @@ bool DeleteDirectiveHandler::DeleteDirectiveTask::RunOnDBThread(
}
void DeleteDirectiveHandler::DeleteDirectiveTask::DoneRunOnMainThread() {
- if (delete_directive_handler_.get()) {
+ if (delete_directive_handler_) {
delete_directive_handler_->FinishProcessing(post_processing_action_,
delete_directives_);
}
diff --git a/chromium/components/history/core/browser/domain_mixing_metrics.cc b/chromium/components/history/core/browser/domain_mixing_metrics.cc
new file mode 100644
index 00000000000..88742939722
--- /dev/null
+++ b/chromium/components/history/core/browser/domain_mixing_metrics.cc
@@ -0,0 +1,150 @@
+// Copyright 2018 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/domain_mixing_metrics.h"
+
+#include "base/containers/flat_map.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+
+namespace history {
+namespace {
+
+// For readability, represents days as times rounded down to a multiple in
+// days from begin_time.
+using Day = base::Time;
+using DomainVisits = base::flat_map<std::string, int>;
+using DomainVisitsPerDay = base::flat_map<Day, DomainVisits>;
+
+// The time intervals in days to compute domain mixing metrics for, sorted
+// in ascending order.
+std::vector<int> NumDaysForMetrics() {
+ return {1, 7, 14, 30};
+}
+
+// Maps a time to the start of a day using ref_start_of_day as the reference
+// time for the start of a day. Some examples:
+//
+// time = 2018-01-02 13:00:00 UTC
+// ref = 2018-01-04 04:00:00 UTC
+// result = 2018-01-02 04:00:00 UTC
+//
+// time = 2018-01-06 03:00:00 UTC
+// ref = 2018-01-04 04:00:00 UTC
+// result = 2018-01-05 04:00:00 UTC
+Day ToStartOfDay(base::Time time, Day ref_start_of_day) {
+ return ref_start_of_day +
+ base::TimeDelta::FromDays((time - ref_start_of_day).InDaysFloored());
+}
+
+// Counts the number of visits per day and per domain as a nested map
+// day -> domain -> num_visits.
+// start_of_day is used as the reference time for the start of a day.
+DomainVisitsPerDay CountDomainVisitsPerDay(
+ base::Time start_of_day,
+ const std::vector<DomainVisit>& domain_visits) {
+ DomainVisitsPerDay domain_visits_per_day;
+ for (const DomainVisit& visit : domain_visits) {
+ const Day day = ToStartOfDay(visit.visit_time(), start_of_day);
+ DomainVisits& domain_visits_for_day = domain_visits_per_day[day];
+ ++domain_visits_for_day[visit.domain()];
+ }
+ return domain_visits_per_day;
+}
+
+// Computes the domain mixing ratio given the number of visits for each domain.
+double ComputeDomainMixingRatio(const DomainVisits& domain_visits) {
+ // First, we extract the domain with the most visits.
+ const auto top_domain = std::max_element(
+ domain_visits.begin(), domain_visits.end(),
+ [](const DomainVisits::value_type& a, const DomainVisits::value_type& b) {
+ return a.second < b.second;
+ });
+
+ // Then we compute the number of visits that are not on the top domain
+ // (secondary domains).
+ int other_visits = 0;
+ for (const auto& domain_num_visits : domain_visits) {
+ if (domain_num_visits.first != top_domain->first)
+ other_visits += domain_num_visits.second;
+ }
+
+ // Finally, we compute the domain mixing ratio which is the ratio of the
+ // number of visits on secondary domains to the total number of visits.
+ // This ratio is equal to 0 if all visits are on the top domain (no domain
+ // mixing) and is close to 1 if most visits are on secondary domains.
+ DCHECK_GT(other_visits + top_domain->second, 0)
+ << "Tried to compute domain mixing for a time range with no domain "
+ "visits, this should never happen as we only compute domain mixing "
+ "for active days.";
+ return static_cast<double>(other_visits) /
+ (other_visits + top_domain->second);
+}
+
+void EmitDomainMixingMetric(const DomainVisits& domain_visits, int num_days) {
+ double domain_mixing_ratio = ComputeDomainMixingRatio(domain_visits);
+ int percentage = gfx::ToRoundedInt(100 * domain_mixing_ratio);
+ switch (num_days) {
+ case 1:
+ UMA_HISTOGRAM_PERCENTAGE("DomainMixing.OneDay", percentage);
+ break;
+ case 7:
+ UMA_HISTOGRAM_PERCENTAGE("DomainMixing.OneWeek", percentage);
+ break;
+ case 14:
+ UMA_HISTOGRAM_PERCENTAGE("DomainMixing.TwoWeeks", percentage);
+ break;
+ case 30:
+ UMA_HISTOGRAM_PERCENTAGE("DomainMixing.OneMonth", percentage);
+ break;
+ default:
+ // This should never happen.
+ NOTREACHED();
+ }
+}
+
+void EmitDomainMixingMetricsForDay(
+ const DomainVisitsPerDay::const_iterator& active_day,
+ const DomainVisitsPerDay& domain_visits_per_day) {
+ DomainVisits domain_visits = active_day->second;
+ // To efficiently compute domain mixing for each of the time periods, we
+ // aggregate domain visits preceding the active day in a single pass.
+ // The metrics to emit are sorted by increasing time period lengths.
+ // We take them in order, aggregate the number of activity days required
+ // for the current one, then move on to the next one.
+ // Reverse iterator, starting at the day before active_day.
+ auto it = std::make_reverse_iterator(active_day);
+ for (const int num_days : NumDaysForMetrics()) {
+ const Day first_day =
+ active_day->first - base::TimeDelta::FromDays(num_days - 1);
+ for (; it != domain_visits_per_day.rend() && it->first >= first_day; ++it) {
+ for (const auto& domain_num_visits : it->second) {
+ domain_visits[domain_num_visits.first] += domain_num_visits.second;
+ }
+ }
+ // We have aggregated all the days within the time window for the current
+ // metric.
+ EmitDomainMixingMetric(domain_visits, num_days);
+ }
+}
+
+} // namespace
+
+void EmitDomainMixingMetrics(const std::vector<DomainVisit>& domain_visits,
+ base::Time start_of_first_day_to_emit) {
+ // We count the visits per domain for each day of user activity.
+ DomainVisitsPerDay domain_visits_per_day =
+ CountDomainVisitsPerDay(start_of_first_day_to_emit, domain_visits);
+
+ // We then compute domain mixing metrics for each day of activity within
+ // [start_of_first_day_to_emit, last_day].
+ for (auto active_day_it =
+ domain_visits_per_day.lower_bound(start_of_first_day_to_emit);
+ active_day_it != domain_visits_per_day.end(); ++active_day_it) {
+ EmitDomainMixingMetricsForDay(active_day_it, domain_visits_per_day);
+ }
+}
+
+} // namespace history \ No newline at end of file
diff --git a/chromium/components/history/core/browser/domain_mixing_metrics.h b/chromium/components/history/core/browser/domain_mixing_metrics.h
new file mode 100644
index 00000000000..7ae2e514446
--- /dev/null
+++ b/chromium/components/history/core/browser/domain_mixing_metrics.h
@@ -0,0 +1,35 @@
+// Copyright 2018 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_DOMAIN_MIXING_METRICS_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_DOMAIN_MIXING_METRICS_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "components/history/core/browser/history_types.h"
+
+namespace history {
+
+// Emits domain mixing metrics given a list of domain visits and the start of
+// the first day to compute metrics for.
+//
+// See http://goto.google.com/chrome-no-searchdomaincheck for more details on
+// what domain mixing metrics are and how they are computed.
+//
+// The domain_visits vector is expected to contain exactly all the domain visits
+// made by the user from start_of_first_day_to_emit - 29 days (to compute the 30
+// day domain mixing metric for the first day) until the end of the last day to
+// compute metrics for.
+//
+// This method wraps the business logic required to compute domain mixing
+// metrics and is exposed for testing purposes to decouple testing the logic
+// that computes the metrics from the database logic.
+void EmitDomainMixingMetrics(const std::vector<DomainVisit>& domain_visits,
+ base::Time start_of_first_day_to_emit);
+
+} // namespace history
+
+#endif \ No newline at end of file
diff --git a/chromium/components/history/core/browser/domain_mixing_metrics_unittest.cc b/chromium/components/history/core/browser/domain_mixing_metrics_unittest.cc
new file mode 100644
index 00000000000..b03bdbf4aec
--- /dev/null
+++ b/chromium/components/history/core/browser/domain_mixing_metrics_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2018 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/domain_mixing_metrics.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/test/histogram_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace history {
+
+class DomainMixingMetricsTest : public testing::Test {
+ protected:
+ base::HistogramTester tester_;
+};
+
+TEST_F(DomainMixingMetricsTest, NoVisits) {
+ base::Time now =
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1523432317);
+ EmitDomainMixingMetrics({}, now);
+
+ // Check that no metrics were emitted.
+ tester_.ExpectTotalCount("DomainMixing.OneDay", 0);
+ tester_.ExpectTotalCount("DomainMixing.OneWeek", 0);
+ tester_.ExpectTotalCount("DomainMixing.TwoWeeks", 0);
+ tester_.ExpectTotalCount("DomainMixing.OneMonth", 0);
+}
+
+TEST_F(DomainMixingMetricsTest, WithVisits) {
+ // Given the following Google domain visits:
+ // - Day 1, 1am, www.google.com
+ // - Day 2, 11pm, www.google.ch
+ // - Day 8, 2am, www.google.ch
+ // - Day 8, 10pm, www.google.fr
+ // this test checks that the correct domain mixing metrics for Day 8 are
+ // emitted:
+ // DomainMixing.OneDay 50% (Day 8 has one query on .ch, one on .fr)
+ // DomainMixing.OneWeek 33% (2 on .ch, 1 on .fr, day 1 is out of range)
+ // DomainMixing.TwoWeeks 50% (2 on .ch, 2 on other domains - 1.fr and 1 .com)
+ // DomainMixing.OneMonth 50% (ditto)
+ base::Time day1 =
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1523432317);
+ base::Time day2 = day1 + base::TimeDelta::FromDays(1);
+ base::Time day8 = day1 + base::TimeDelta::FromDays(7);
+ EmitDomainMixingMetrics(
+ {
+ DomainVisit("www.google.com", day1 + base::TimeDelta::FromHours(1)),
+ DomainVisit("www.google.ch", day2 + base::TimeDelta::FromHours(23)),
+ DomainVisit("www.google.ch", day8 + base::TimeDelta::FromHours(2)),
+ DomainVisit("www.google.fr", day8 + base::TimeDelta::FromHours(22)),
+ },
+ day8);
+
+ tester_.ExpectUniqueSample("DomainMixing.OneDay", 50, 1);
+ tester_.ExpectUniqueSample("DomainMixing.OneWeek", 33, 1);
+ tester_.ExpectUniqueSample("DomainMixing.TwoWeeks", 50, 1);
+ tester_.ExpectUniqueSample("DomainMixing.OneMonth", 50, 1);
+}
+
+TEST_F(DomainMixingMetricsTest, WithInactiveDays) {
+ base::Time day1 =
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1523432317);
+ base::Time day3 = day1 + base::TimeDelta::FromDays(2);
+ EmitDomainMixingMetrics(
+ {
+ DomainVisit("www.google.com", day1),
+ DomainVisit("www.google.ch", day3),
+ },
+ day1);
+
+ // Check that no metrics are emitted for day2 when the user was inactive.
+ tester_.ExpectTotalCount("DomainMixing.OneDay", 2);
+ tester_.ExpectBucketCount("DomainMixing.OneDay", 0, 2); // Day 1 and 3.
+ tester_.ExpectTotalCount("DomainMixing.OneWeek", 2);
+ tester_.ExpectBucketCount("DomainMixing.OneWeek", 0, 1); // Day 1.
+ tester_.ExpectBucketCount("DomainMixing.OneWeek", 50, 1); // Day 3.
+ tester_.ExpectTotalCount("DomainMixing.TwoWeeks", 2);
+ tester_.ExpectBucketCount("DomainMixing.TwoWeeks", 0, 1); // Day 1.
+ tester_.ExpectBucketCount("DomainMixing.TwoWeeks", 50, 1); // Day 3.
+ tester_.ExpectTotalCount("DomainMixing.OneMonth", 2);
+ tester_.ExpectBucketCount("DomainMixing.OneMonth", 0, 1); // Day 1.
+ tester_.ExpectBucketCount("DomainMixing.OneMonth", 50, 1); // Day 3.
+}
+
+} // namespace history \ No newline at end of file
diff --git a/chromium/components/history/core/browser/download_constants.h b/chromium/components/history/core/browser/download_constants.h
index ea21725fafa..78530f340ce 100644
--- a/chromium/components/history/core/browser/download_constants.h
+++ b/chromium/components/history/core/browser/download_constants.h
@@ -35,6 +35,7 @@ enum class DownloadDangerType {
USER_VALIDATED = 6,
DANGEROUS_HOST = 7,
POTENTIALLY_UNWANTED = 8,
+ WHITELISTED_BY_POLICY = 9,
};
// DownloadId represents the id of a DownloadRow into the DownloadDatabase.
diff --git a/chromium/components/history/core/browser/download_types.cc b/chromium/components/history/core/browser/download_types.cc
index e75081e5b1c..1c740856649 100644
--- a/chromium/components/history/core/browser/download_types.cc
+++ b/chromium/components/history/core/browser/download_types.cc
@@ -63,6 +63,7 @@ DownloadDangerType IntToDownloadDangerType(int danger_type) {
case DownloadDangerType::USER_VALIDATED:
case DownloadDangerType::DANGEROUS_HOST:
case DownloadDangerType::POTENTIALLY_UNWANTED:
+ case DownloadDangerType::WHITELISTED_BY_POLICY:
return static_cast<DownloadDangerType>(danger_type);
case DownloadDangerType::INVALID:
@@ -100,6 +101,8 @@ std::ostream& operator<<(std::ostream& stream, DownloadDangerType danger_type) {
return stream << "history::DownloadDangerType::DANGEROUS_HOST";
case DownloadDangerType::POTENTIALLY_UNWANTED:
return stream << "history::DownloadDangerType::POTENTIALLY_UNWANTED";
+ case DownloadDangerType::WHITELISTED_BY_POLICY:
+ return stream << "history::DownloadDangerType::WHITELISTED_BY_POLICY";
}
NOTREACHED();
return stream;
diff --git a/chromium/components/history/core/browser/expire_history_backend.cc b/chromium/components/history/core/browser/expire_history_backend.cc
index e55dc56bf4e..ef0b2e3dc22 100644
--- a/chromium/components/history/core/browser/expire_history_backend.cc
+++ b/chromium/components/history/core/browser/expire_history_backend.cc
@@ -13,13 +13,13 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/containers/flat_set.h"
-#include "base/feature_list.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
+#include "build/build_config.h"
#include "components/history/core/browser/history_backend_client.h"
#include "components/history/core/browser/history_backend_notifier.h"
#include "components/history/core/browser/history_database.h"
@@ -117,6 +117,11 @@ const int kExpirationDelaySec = 30;
// iteration, so we want to wait longer before checking to avoid wasting CPU.
const int kExpirationEmptyDelayMin = 5;
+// If the expiration timer is delayed by over an hour, then assume that the
+// machine went to sleep.
+constexpr base::TimeDelta kExpirationSleepWakeupThreshold =
+ base::TimeDelta::FromHours(1);
+
// The minimum number of hours between checking for old on-demand favicons that
// should be cleared.
const int kClearOnDemandFaviconsIntervalHours = 24;
@@ -134,8 +139,12 @@ bool IsAnyURLBookmarked(HistoryBackendClient* backend_client,
namespace internal {
-const base::Feature kClearOldOnDemandFavicons{
- "ClearOldOnDemandFavicons", base::FEATURE_DISABLED_BY_DEFAULT};
+// Clearing old on-demand favicons is only enabled on mobile.
+#if defined(OS_ANDROID) || defined(OS_IOS)
+constexpr bool kClearOldOnDemandFaviconsEnabled = true;
+#else
+constexpr bool kClearOldOnDemandFaviconsEnabled = false;
+#endif
const int kOnDemandFaviconIsOldAfterDays = 30;
@@ -213,7 +222,7 @@ void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) {
DeleteFaviconsIfPossible(&effects);
BroadcastNotifications(&effects, DELETION_USER_INITIATED,
- DeletionTimeRange::Invalid());
+ DeletionTimeRange::Invalid(), base::nullopt);
}
void ExpireHistoryBackend::ExpireHistoryBetween(
@@ -239,10 +248,8 @@ void ExpireHistoryBackend::ExpireHistoryBetween(
visits.push_back(*visit);
}
}
- DeletionTimeRange time_range = restrict_urls.empty()
- ? DeletionTimeRange(begin_time, end_time)
- : DeletionTimeRange::Invalid();
- ExpireVisitsInternal(visits, time_range);
+ DeletionTimeRange time_range(begin_time, end_time);
+ ExpireVisitsInternal(visits, time_range, restrict_urls);
}
void ExpireHistoryBackend::ExpireHistoryForTimes(
@@ -265,12 +272,13 @@ void ExpireHistoryBackend::ExpireHistoryForTimes(
}
void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) {
- ExpireVisitsInternal(visits, DeletionTimeRange::Invalid());
+ ExpireVisitsInternal(visits, DeletionTimeRange::Invalid(), {});
}
void ExpireHistoryBackend::ExpireVisitsInternal(
const VisitVector& visits,
- const DeletionTimeRange& time_range) {
+ const DeletionTimeRange& time_range,
+ const std::set<GURL>& restrict_urls) {
if (visits.empty())
return;
@@ -287,7 +295,9 @@ void ExpireHistoryBackend::ExpireVisitsInternal(
// and we don't want to leave any evidence.
ExpireURLsForVisits(visits_and_redirects, &effects);
DeleteFaviconsIfPossible(&effects);
- BroadcastNotifications(&effects, DELETION_USER_INITIATED, time_range);
+ BroadcastNotifications(
+ &effects, DELETION_USER_INITIATED, time_range,
+ restrict_urls.empty() ? base::Optional<std::set<GURL>>() : restrict_urls);
// Pick up any bits possibly left over.
ParanoidExpireHistory();
@@ -301,7 +311,7 @@ void ExpireHistoryBackend::ExpireVisitsInternal(
}
}
-void ExpireHistoryBackend::ExpireHistoryBefore(base::Time end_time) {
+void ExpireHistoryBackend::ExpireHistoryBeforeForTesting(base::Time end_time) {
if (!main_db_)
return;
@@ -372,14 +382,15 @@ void ExpireHistoryBackend::DeleteFaviconsIfPossible(DeleteEffects* effects) {
void ExpireHistoryBackend::BroadcastNotifications(
DeleteEffects* effects,
DeletionType type,
- const DeletionTimeRange& time_range) {
+ const DeletionTimeRange& time_range,
+ base::Optional<std::set<GURL>> restrict_urls) {
if (!effects->modified_urls.empty()) {
notifier_->NotifyURLsModified(effects->modified_urls);
}
if (!effects->deleted_urls.empty() || time_range.IsValid()) {
- notifier_->NotifyURLsDeleted(time_range, type == DELETION_EXPIRED,
- effects->deleted_urls,
- effects->deleted_favicons);
+ notifier_->NotifyURLsDeleted(DeletionInfo(
+ time_range, type == DELETION_EXPIRED, std::move(effects->deleted_urls),
+ std::move(effects->deleted_favicons), std::move(restrict_urls)));
}
}
@@ -465,12 +476,7 @@ void ExpireHistoryBackend::ExpireURLsForVisits(const VisitVector& visits,
ui::PAGE_TRANSITION_RELOAD)) {
cur.visit_count++;
}
- if (ui::PageTransitionIsNewNavigation(visits[i].transition) &&
- ((ui::PageTransitionCoreTypeIs(visits[i].transition,
- ui::PAGE_TRANSITION_TYPED) &&
- !ui::PageTransitionIsRedirect(visits[i].transition)) ||
- ui::PageTransitionCoreTypeIs(visits[i].transition,
- ui::PAGE_TRANSITION_KEYWORD_GENERATED)))
+ if (visits[i].incremented_omnibox_typed_score)
cur.typed_count++;
}
@@ -524,6 +530,7 @@ void ExpireHistoryBackend::ScheduleExpire() {
delay = base::TimeDelta::FromSeconds(kExpirationDelaySec);
}
+ expected_expiration_time_ = base::Time::Now() + delay;
task_runner_->PostDelayedTask(
FROM_HERE,
base::Bind(&ExpireHistoryBackend::DoExpireIteration,
@@ -534,6 +541,21 @@ void ExpireHistoryBackend::ScheduleExpire() {
void ExpireHistoryBackend::DoExpireIteration() {
DCHECK(!work_queue_.empty()) << "queue has to be non-empty";
+ // If the timer is firing more than an hour later than expected, than the
+ // machine likely just woke from sleep/hibernation. There is potentially a lot
+ // of expiring that needs to happen. Wait for 5 minutes before starting to do
+ // any expiry, to avoid conflicting with other work that happens on waking
+ // from sleep.
+ if (base::Time::Now() - expected_expiration_time_ >
+ kExpirationSleepWakeupThreshold) {
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ExpireHistoryBackend::ScheduleExpire,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMinutes(kExpirationEmptyDelayMin));
+ return;
+ }
+
const ExpiringVisitsReader* reader = work_queue_.front();
bool more_to_expire = ExpireSomeOldHistory(
GetCurrentExpirationTime(), reader, kNumExpirePerIteration);
@@ -543,7 +565,7 @@ void ExpireHistoryBackend::DoExpireIteration() {
// If there are more items to expire, add the reader back to the queue, thus
// creating a new task for future iterations.
work_queue_.push(reader);
- } else {
+ } else if (internal::kClearOldOnDemandFaviconsEnabled) {
// Otherwise do a final clean-up - remove old favicons not bound to visits.
ClearOldOnDemandFaviconsIfPossible(
base::Time::Now() -
@@ -558,9 +580,6 @@ void ExpireHistoryBackend::ClearOldOnDemandFaviconsIfPossible(
if (!thumb_db_)
return;
- if (!base::FeatureList::IsEnabled(internal::kClearOldOnDemandFavicons))
- return;
-
// Extra precaution to avoid repeated calls to GetOldOnDemandFavicons() close
// in time, since it can be fairly expensive.
if (expiration_threshold <
@@ -590,7 +609,7 @@ void ExpireHistoryBackend::ClearOldOnDemandFaviconsIfPossible(
}
BroadcastNotifications(&effects, DELETION_EXPIRED,
- DeletionTimeRange::Invalid());
+ DeletionTimeRange::Invalid(), base::nullopt);
}
bool ExpireHistoryBackend::ExpireSomeOldHistory(
@@ -613,10 +632,9 @@ bool ExpireHistoryBackend::ExpireSomeOldHistory(
DeleteVisitRelatedInfo(deleted_visits, &deleted_effects);
ExpireURLsForVisits(deleted_visits, &deleted_effects);
DeleteFaviconsIfPossible(&deleted_effects);
- DeletionTimeRange time_range =
- more_to_expire ? DeletionTimeRange::Invalid()
- : DeletionTimeRange(base::Time(), end_time);
- BroadcastNotifications(&deleted_effects, DELETION_EXPIRED, time_range);
+
+ BroadcastNotifications(&deleted_effects, DELETION_EXPIRED,
+ DeletionTimeRange::Invalid(), base::nullopt);
return more_to_expire;
}
diff --git a/chromium/components/history/core/browser/expire_history_backend.h b/chromium/components/history/core/browser/expire_history_backend.h
index 1c89f47e8fd..c936412effc 100644
--- a/chromium/components/history/core/browser/expire_history_backend.h
+++ b/chromium/components/history/core/browser/expire_history_backend.h
@@ -20,7 +20,6 @@ class GURL;
class TestingProfile;
namespace base {
-struct Feature;
class SequencedTaskRunner;
}
@@ -44,9 +43,6 @@ class ExpiringVisitsReader {
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
@@ -96,8 +92,8 @@ class ExpireHistoryBackend {
void ExpireVisits(const VisitVector& visits);
// Expires all visits before and including the given time, updating the URLs
- // accordingly. Currently only used for testing.
- void ExpireHistoryBefore(base::Time end_time);
+ // accordingly.
+ void ExpireHistoryBeforeForTesting(base::Time end_time);
// Returns the current cut-off time before which we will start expiring stuff.
// Note that this as an absolute time rather than a delta, so the caller
@@ -202,7 +198,8 @@ class ExpireHistoryBackend {
void ExpireURLsForVisits(const VisitVector& visits, DeleteEffects* effects);
void ExpireVisitsInternal(const VisitVector& visits,
- const DeletionTimeRange& time_range);
+ const DeletionTimeRange& time_range,
+ const std::set<GURL>& restrict_urls);
// Deletes the favicons listed in |effects->affected_favicons| if they are
// unsued. Fails silently (we don't care about favicons so much, so don't want
@@ -223,7 +220,8 @@ class ExpireHistoryBackend {
// Broadcasts URL modified and deleted notifications.
void BroadcastNotifications(DeleteEffects* effects,
DeletionType type,
- const DeletionTimeRange& time_range);
+ const DeletionTimeRange& time_range,
+ base::Optional<std::set<GURL>> restrict_urls);
// Schedules a call to DoExpireIteration.
void ScheduleExpire();
@@ -272,6 +270,9 @@ class ExpireHistoryBackend {
// The threshold for "old" history where we will automatically delete it.
base::TimeDelta expiration_threshold_;
+ // The time at which we expect the expiration code to run.
+ base::Time expected_expiration_time_;
+
// The lastly used threshold for "old" on-demand favicons.
base::Time last_on_demand_expiration_threshold_;
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 2e98f96b093..a0215c0a522 100644
--- a/chromium/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
@@ -16,7 +16,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
@@ -105,9 +105,10 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
// |expired|, or manually deleted.
void EnsureURLInfoGone(const URLRow& row, bool expired);
- DeletionTimeRange GetLastDeletionTimeRange() {
- EXPECT_FALSE(urls_deleted_notifications_.empty());
- return std::get<0>(urls_deleted_notifications_.back());
+ const DeletionInfo* GetLastDeletionInfo() {
+ if (urls_deleted_notifications_.empty())
+ return nullptr;
+ return &urls_deleted_notifications_.back();
}
// Returns whether HistoryBackendNotifier::NotifyURLsModified was
@@ -148,8 +149,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
typedef std::vector<URLRows> URLsModifiedNotificationList;
URLsModifiedNotificationList urls_modified_notifications_;
- typedef std::vector<std::tuple<DeletionTimeRange, bool, URLRows>>
- URLsDeletedNotificationList;
+ typedef std::vector<DeletionInfo> URLsDeletedNotificationList;
URLsDeletedNotificationList urls_deleted_notifications_;
private:
@@ -191,7 +191,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
top_sites_->ShutdownOnUIThread();
top_sites_ = nullptr;
- if (base::MessageLoop::current())
+ if (base::MessageLoopCurrent::Get())
base::RunLoop().RunUntilIdle();
pref_service_.reset();
@@ -207,11 +207,8 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
void NotifyURLsModified(const URLRows& rows) override {
urls_modified_notifications_.push_back(rows);
}
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& rows,
- const std::set<GURL>& favicon_urls) override {
- urls_deleted_notifications_.push_back(std::tie(time_range, expired, rows));
+ void NotifyURLsDeleted(DeletionInfo deletion_info) override {
+ urls_deleted_notifications_.push_back(std::move(deletion_info));
}
};
@@ -229,7 +226,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
// added to the given arrays.
void ExpireHistoryTest::AddExampleData(URLID url_ids[3],
base::Time visit_times[4]) {
- if (!main_db_.get())
+ if (!main_db_)
return;
// Four times for each visit.
@@ -289,6 +286,7 @@ void ExpireHistoryTest::AddExampleData(URLID url_ids[3],
visit_row3.url_id = url_ids[1];
visit_row3.visit_time = visit_times[2];
visit_row3.transition = ui::PAGE_TRANSITION_TYPED;
+ visit_row3.incremented_omnibox_typed_score = true;
main_db_->AddVisit(&visit_row3, SOURCE_BROWSED);
VisitRow visit_row4;
@@ -311,23 +309,24 @@ void ExpireHistoryTest::AddExampleSourceData(const GURL& url, URLID* id) {
// Four times for each visit.
VisitRow visit_row1(url_id, last_visit_time - base::TimeDelta::FromDays(4), 0,
- ui::PAGE_TRANSITION_TYPED, 0);
+ ui::PAGE_TRANSITION_TYPED, 0, true);
main_db_->AddVisit(&visit_row1, SOURCE_SYNCED);
VisitRow visit_row2(url_id, last_visit_time - base::TimeDelta::FromDays(3), 0,
- ui::PAGE_TRANSITION_TYPED, 0);
+ ui::PAGE_TRANSITION_TYPED, 0, true);
main_db_->AddVisit(&visit_row2, SOURCE_BROWSED);
VisitRow visit_row3(url_id, last_visit_time - base::TimeDelta::FromDays(2), 0,
- ui::PAGE_TRANSITION_TYPED, 0);
+ ui::PAGE_TRANSITION_TYPED, 0, true);
main_db_->AddVisit(&visit_row3, SOURCE_EXTENSION);
- VisitRow visit_row4(url_id, last_visit_time, 0, ui::PAGE_TRANSITION_TYPED, 0);
+ VisitRow visit_row4(url_id, last_visit_time, 0, ui::PAGE_TRANSITION_TYPED, 0,
+ true);
main_db_->AddVisit(&visit_row4, SOURCE_FIREFOX_IMPORTED);
}
bool ExpireHistoryTest::HasFavicon(favicon_base::FaviconID favicon_id) {
- if (!thumb_db_.get() || favicon_id == 0)
+ if (!thumb_db_ || favicon_id == 0)
return false;
return thumb_db_->GetFaviconHeader(favicon_id, nullptr, nullptr);
}
@@ -373,9 +372,9 @@ void ExpireHistoryTest::EnsureURLInfoGone(const URLRow& row, bool expired) {
// EXPECT_FALSE(HasThumbnail(row.id()));
bool found_delete_notification = false;
- for (const auto& tuple : urls_deleted_notifications_) {
- EXPECT_EQ(expired, std::get<1>(tuple));
- const history::URLRows& rows(std::get<2>(tuple));
+ for (const auto& info : urls_deleted_notifications_) {
+ EXPECT_EQ(expired, info.is_from_expiration());
+ const history::URLRows& rows(info.deleted_rows());
history::URLRows::const_iterator it_row = std::find_if(
rows.begin(), rows.end(), history::URLRow::URLRowHasURL(row.url()));
if (it_row != rows.end()) {
@@ -622,8 +621,8 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsUnstarred) {
// This should delete the last two visits.
std::set<GURL> restrict_urls;
expirer_.ExpireHistoryBetween(restrict_urls, visit_times[2], base::Time());
- EXPECT_EQ(GetLastDeletionTimeRange().begin(), visit_times[2]);
- EXPECT_EQ(GetLastDeletionTimeRange().end(), base::Time());
+ EXPECT_EQ(GetLastDeletionInfo()->time_range().begin(), visit_times[2]);
+ EXPECT_EQ(GetLastDeletionInfo()->time_range().end(), base::Time());
// Verify that the middle URL had its last visit deleted only.
visits.clear();
@@ -813,7 +812,7 @@ TEST_F(ExpireHistoryTest, FlushURLsForTimes) {
times.push_back(visit_times[3]);
times.push_back(visit_times[2]);
expirer_.ExpireHistoryForTimes(times);
- EXPECT_FALSE(GetLastDeletionTimeRange().IsValid());
+ EXPECT_FALSE(GetLastDeletionInfo()->time_range().IsValid());
// Verify that the middle URL had its last visit deleted only.
visits.clear();
@@ -862,9 +861,12 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsUnstarredRestricted) {
ASSERT_EQ(1U, visits.size());
// This should delete the last two visits.
- std::set<GURL> restrict_urls;
- restrict_urls.insert(url_row1.url());
+ std::set<GURL> restrict_urls = {url_row1.url()};
expirer_.ExpireHistoryBetween(restrict_urls, visit_times[2], base::Time());
+ EXPECT_EQ(GetLastDeletionInfo()->time_range().begin(), visit_times[2]);
+ EXPECT_EQ(GetLastDeletionInfo()->time_range().end(), base::Time());
+ EXPECT_EQ(GetLastDeletionInfo()->deleted_rows().size(), 0U);
+ EXPECT_EQ(GetLastDeletionInfo()->restrict_urls()->size(), 1U);
// Verify that the middle URL had its last visit deleted only.
visits.clear();
@@ -957,7 +959,7 @@ TEST_F(ExpireHistoryTest, ExpireHistoryBeforeUnstarred) {
ASSERT_TRUE(main_db_->GetURLRow(url_ids[2], &url_row2));
// Expire the oldest two visits.
- expirer_.ExpireHistoryBefore(visit_times[1]);
+ expirer_.ExpireHistoryBeforeForTesting(visit_times[1]);
// The first URL should be deleted along with its sole visit. The second URL
// itself should not be affected, as there is still one more visit to it, but
@@ -975,7 +977,7 @@ TEST_F(ExpireHistoryTest, ExpireHistoryBeforeUnstarred) {
// Now expire one more visit so that the second URL should be removed. The
// third URL and its visit should be intact.
ClearLastNotifications();
- expirer_.ExpireHistoryBefore(visit_times[2]);
+ expirer_.ExpireHistoryBeforeForTesting(visit_times[2]);
EnsureURLInfoGone(url_row1, true);
EXPECT_TRUE(main_db_->GetURLRow(url_ids[2], &temp_row));
main_db_->GetVisitsForURL(temp_row.id(), &visits);
@@ -998,7 +1000,7 @@ TEST_F(ExpireHistoryTest, ExpireHistoryBeforeStarred) {
// Now expire the first three visits (first two URLs). The first three visits
// should be deleted, but the URL records themselves should not, as they are
// starred.
- expirer_.ExpireHistoryBefore(visit_times[2]);
+ expirer_.ExpireHistoryBeforeForTesting(visit_times[2]);
URLRow temp_row;
ASSERT_TRUE(main_db_->GetURLRow(url_ids[0], &temp_row));
@@ -1031,19 +1033,19 @@ TEST_F(ExpireHistoryTest, ExpireSomeOldHistory) {
// Deleting a time range with no URLs should return false (nothing found).
EXPECT_FALSE(expirer_.ExpireSomeOldHistory(
visit_times[0] - base::TimeDelta::FromDays(100), reader, 1));
- EXPECT_EQ(GetLastDeletionTimeRange().begin(), base::Time());
- EXPECT_EQ(GetLastDeletionTimeRange().end(),
- visit_times[0] - base::TimeDelta::FromDays(100));
+ EXPECT_EQ(nullptr, GetLastDeletionInfo());
// Deleting a time range with not up the the max results should also return
// false (there will only be one visit deleted in this range).
EXPECT_FALSE(expirer_.ExpireSomeOldHistory(visit_times[0], reader, 2));
- EXPECT_EQ(GetLastDeletionTimeRange().begin(), base::Time());
- EXPECT_EQ(GetLastDeletionTimeRange().end(), visit_times[0]);
+ EXPECT_EQ(1U, GetLastDeletionInfo()->deleted_rows().size());
+ EXPECT_FALSE(GetLastDeletionInfo()->time_range().IsValid());
+ ClearLastNotifications();
// Deleting a time range with the max number of results should return true
// (max deleted).
EXPECT_TRUE(expirer_.ExpireSomeOldHistory(visit_times[2], reader, 1));
+ EXPECT_EQ(nullptr, GetLastDeletionInfo());
}
TEST_F(ExpireHistoryTest, ExpiringVisitsReader) {
@@ -1079,9 +1081,6 @@ TEST_F(ExpireHistoryTest, ExpiringVisitsReader) {
// Test that ClearOldOnDemandFaviconsIfPossible() deletes favicons associated
// only to unstarred page URLs.
TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteUnstarred) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
-
// The blob does not encode any real bitmap, obviously.
const unsigned char kBlob[] = "0";
scoped_refptr<base::RefCountedBytes> favicon(
@@ -1108,9 +1107,6 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteUnstarred) {
// Test that ClearOldOnDemandFaviconsIfPossible() deletes favicons associated to
// at least one starred page URL.
TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesNotDeleteStarred) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
-
// The blob does not encode any real bitmap, obviously.
const unsigned char kBlob[] = "0";
scoped_refptr<base::RefCountedBytes> favicon(
@@ -1147,9 +1143,6 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesNotDeleteStarred) {
// Test that ClearOldOnDemandFaviconsIfPossible() has effect if the last
// clearing was long time age (such as 2 days ago).
TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteAfterLongDelay) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
-
// Previous clearing (2 days ago).
expirer_.ClearOldOnDemandFaviconsIfPossible(GetOldFaviconThreshold() -
base::TimeDelta::FromDays(2));
@@ -1181,9 +1174,6 @@ TEST_F(ExpireHistoryTest, ClearOldOnDemandFaviconsDoesDeleteAfterLongDelay) {
// at least one starred page URL.
TEST_F(ExpireHistoryTest,
ClearOldOnDemandFaviconsDoesNotDeleteAfterShortDelay) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(internal::kClearOldOnDemandFavicons);
-
// Previous clearing (5 minutes ago).
expirer_.ClearOldOnDemandFaviconsIfPossible(GetOldFaviconThreshold() -
base::TimeDelta::FromMinutes(5));
diff --git a/chromium/components/history/core/browser/history_backend.cc b/chromium/components/history/core/browser/history_backend.cc
index 851bf1c6818..478d3985a87 100644
--- a/chromium/components/history/core/browser/history_backend.cc
+++ b/chromium/components/history/core/browser/history_backend.cc
@@ -171,6 +171,18 @@ HistoryBackendHelper::~HistoryBackendHelper() {
// HistoryBackend --------------------------------------------------------------
+// static
+bool HistoryBackend::IsTypedIncrement(ui::PageTransition transition) {
+ if (ui::PageTransitionIsNewNavigation(transition) &&
+ ((ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
+ !ui::PageTransitionIsRedirect(transition)) ||
+ ui::PageTransitionCoreTypeIs(transition,
+ ui::PAGE_TRANSITION_KEYWORD_GENERATED))) {
+ return true;
+ }
+ return false;
+}
+
HistoryBackend::HistoryBackend(
Delegate* delegate,
std::unique_ptr<HistoryBackendClient> backend_client,
@@ -413,6 +425,8 @@ OriginCountAndLastVisitMap HistoryBackend::GetCountsAndLastVisitForOrigins(
const std::set<GURL>& origins) const {
if (!db_)
return OriginCountAndLastVisitMap();
+ if (origins.empty())
+ return OriginCountAndLastVisitMap();
URLDatabase::URLEnumerator it;
if (!db_->InitURLEnumeratorForEverything(&it))
@@ -775,15 +789,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
ui::PageTransition transition,
bool hidden,
VisitSource visit_source) {
- // NOTE: This code must stay in sync with
- // ExpireHistoryBackend::ExpireURLsForVisits().
- int typed_increment = 0;
- if (ui::PageTransitionIsNewNavigation(transition) &&
- ((ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
- !ui::PageTransitionIsRedirect(transition)) ||
- ui::PageTransitionCoreTypeIs(transition,
- ui::PAGE_TRANSITION_KEYWORD_GENERATED)))
- typed_increment = 1;
+ const bool typed_increment = IsTypedIncrement(transition);
if (!host_ranks_.empty() && visit_source == SOURCE_BROWSED &&
(transition & ui::PAGE_TRANSITION_CHAIN_END)) {
@@ -798,7 +804,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
if (!ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD))
url_info.set_visit_count(url_info.visit_count() + 1);
if (typed_increment)
- url_info.set_typed_count(url_info.typed_count() + typed_increment);
+ url_info.set_typed_count(url_info.typed_count() + 1);
if (url_info.last_visit() < time)
url_info.set_last_visit(time);
@@ -810,7 +816,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
} else {
// Addition of a new row.
url_info.set_visit_count(1);
- url_info.set_typed_count(typed_increment);
+ url_info.set_typed_count(typed_increment ? 1 : 0);
url_info.set_last_visit(time);
url_info.set_hidden(hidden);
@@ -823,7 +829,8 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
}
// Add the visit with the time to the database.
- VisitRow visit_info(url_id, time, referring_visit, transition, 0);
+ VisitRow visit_info(url_id, time, referring_visit, transition, 0,
+ typed_increment);
VisitID visit_id = db_->AddVisit(&visit_info, visit_source);
if (visit_info.visit_time < first_recorded_time_)
@@ -879,7 +886,7 @@ void HistoryBackend::AddPagesWithDetails(const URLRows& urls,
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
ui::PAGE_TRANSITION_CHAIN_START |
ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ 0, false);
if (!db_->AddVisit(&visit_info, visit_source)) {
NOTREACHED() << "Adding visit failed.";
return;
@@ -1633,11 +1640,9 @@ void HistoryBackend::MergeFavicon(
favicon_base::FaviconID favicon_id =
thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type);
- bool favicon_created = false;
if (!favicon_id) {
// There is no favicon at |icon_url|, create it.
favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
- favicon_created = true;
}
std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
@@ -1776,9 +1781,7 @@ void HistoryBackend::MergeFavicon(
SendFaviconChangedNotificationForPageAndRedirects(page_url);
}
- if (!favicon_created && (!bitmap_identical || favicon_bitmaps_copied)) {
- // If there was a favicon at |icon_url| prior to MergeFavicon() being
- // called, there may be page URLs which also use the favicon at |icon_url|.
+ if (!bitmap_identical || favicon_bitmaps_copied) {
// Notify the UI that the favicon has changed for |icon_url|.
SendFaviconChangedNotificationForIconURL(icon_url);
}
@@ -1995,10 +1998,8 @@ bool HistoryBackend::SetFaviconsImpl(const base::flat_set<GURL>& page_urls,
}
}
- if (favicon_data_modified && !favicon_created) {
- // If there was a favicon at |icon_url| prior to SetFavicons() being called,
- // there may be page URLs which also use the favicon at |icon_url|. Notify
- // the UI that the favicon has changed for |icon_url|.
+ if (favicon_data_modified) {
+ // Notify the UI that the favicon has changed for |icon_url|.
SendFaviconChangedNotificationForIconURL(icon_url);
}
ScheduleCommit();
@@ -2526,6 +2527,13 @@ void HistoryBackend::ExpireHistory(
}
}
+void HistoryBackend::ExpireHistoryBeforeForTesting(base::Time end_time) {
+ if (!db_)
+ return;
+
+ expirer_.ExpireHistoryBeforeForTesting(end_time);
+}
+
void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
if (!db_)
return;
@@ -2549,15 +2557,13 @@ void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) {
db_diagnostics_ = db_->GetDiagnosticInfo(error, stmt);
- // Notify SyncBridge about storage error. It will report failure to sync
- // engine and stop accepting remote updates.
- if (typed_url_sync_bridge_)
- typed_url_sync_bridge_->OnDatabaseError();
-
// Don't just do the close/delete here, as we are being called by |db| and
// that seems dangerous.
- // TODO(shess): Consider changing KillHistoryDatabase() to use
- // RazeAndClose(). Then it can be cleared immediately.
+ // TODO(https://crbug.com/854258): It is also dangerous to kill the database
+ // by a posted task: tasks that run before KillHistoryDatabase still can try
+ // to use the broken database. Consider protecting against other tasks using
+ // the DB or consider changing KillHistoryDatabase() to use RazeAndClose()
+ // (then it can be cleared immediately).
task_runner_->PostTask(
FROM_HERE, base::Bind(&HistoryBackend::KillHistoryDatabase, this));
}
@@ -2568,6 +2574,11 @@ void HistoryBackend::KillHistoryDatabase() {
if (!db_)
return;
+ // Notify SyncBridge about storage error. It will report failure to sync
+ // engine and stop accepting remote updates.
+ if (typed_url_sync_bridge_)
+ typed_url_sync_bridge_->OnDatabaseError();
+
// Rollback transaction because Raze() cannot be called from within a
// transaction.
db_->RollbackTransaction();
@@ -2635,19 +2646,22 @@ void HistoryBackend::NotifyURLsModified(const URLRows& rows) {
delegate_->NotifyURLsModified(rows);
}
-void HistoryBackend::NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& rows,
- const std::set<GURL>& favicon_urls) {
- URLRows copied_rows(rows);
+void HistoryBackend::NotifyURLsDeleted(DeletionInfo deletion_info) {
+ std::set<GURL> origins;
+ for (const history::URLRow& row : deletion_info.deleted_rows())
+ origins.insert(row.url().GetOrigin());
+
+ deletion_info.set_deleted_urls_origin_map(
+ GetCountsAndLastVisitForOrigins(origins));
+
for (HistoryBackendObserver& observer : observers_) {
- observer.OnURLsDeleted(this, time_range.IsAllTime(), expired, copied_rows,
- favicon_urls);
+ observer.OnURLsDeleted(
+ this, deletion_info.IsAllHistory(), deletion_info.is_from_expiration(),
+ deletion_info.deleted_rows(), deletion_info.favicon_urls());
}
if (delegate_)
- delegate_->NotifyURLsDeleted(time_range, expired, copied_rows,
- favicon_urls);
+ delegate_->NotifyURLsDeleted(std::move(deletion_info));
}
// Deleting --------------------------------------------------------------------
@@ -2704,8 +2718,7 @@ void HistoryBackend::DeleteAllHistory() {
// Send out the notification that history is cleared. The in-memory database
// will pick this up and clear itself.
- NotifyURLsDeleted(DeletionTimeRange::AllTime(), false, URLRows(),
- std::set<GURL>());
+ NotifyURLsDeleted(DeletionInfo::ForAllHistory());
}
bool HistoryBackend::ClearAllThumbnailHistory(
diff --git a/chromium/components/history/core/browser/history_backend.h b/chromium/components/history/core/browser/history_backend.h
index fa77efd2dfe..be693853337 100644
--- a/chromium/components/history/core/browser/history_backend.h
+++ b/chromium/components/history/core/browser/history_backend.h
@@ -143,10 +143,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Notify HistoryService that some or all of the URLs have been deleted.
// The event will be forwarded to the HistoryServiceObservers in the correct
// thread.
- virtual void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) = 0;
+ virtual void NotifyURLsDeleted(DeletionInfo deletion_info) = 0;
// Notify HistoryService that some keyword has been searched using omnibox.
// The event will be forwarded to the HistoryServiceObservers in the correct
@@ -164,6 +161,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
virtual void DBLoaded() = 0;
};
+ // Check if the transition should increment the typed_count of a visit.
+ static bool IsTypedIncrement(ui::PageTransition transition);
+
// Init must be called to complete object creation. This object can be
// constructed on any thread, but all other functions including Init() must
// be called on the history thread.
@@ -439,6 +439,10 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// of ExpireHistoryBetween().
void ExpireHistory(const std::vector<ExpireHistoryArgs>& expire_list);
+ // Expires all visits before and including the given time, updating the URLs
+ // accordingly.
+ void ExpireHistoryBeforeForTesting(base::Time end_time);
+
// Bookmarks -----------------------------------------------------------------
// Notification that a URL is no longer bookmarked. If there are no visits
@@ -818,10 +822,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
const RedirectList& redirects,
base::Time visit_time) override;
void NotifyURLsModified(const URLRows& rows) override;
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& rows,
- const std::set<GURL>& favicon_urls) override;
+ void NotifyURLsDeleted(DeletionInfo deletion_info) override;
void RecordTopHostsMetrics(const GURL& url);
diff --git a/chromium/components/history/core/browser/history_backend_db_unittest.cc b/chromium/components/history/core/browser/history_backend_db_unittest.cc
index 077da13c3dd..9f3ac0fad31 100644
--- a/chromium/components/history/core/browser/history_backend_db_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_db_unittest.cc
@@ -1583,6 +1583,121 @@ TEST_F(HistoryBackendDBTest, MigrateDownloadSliceFinished) {
}
}
+// Test to verify the incremented_omnibox_typed_score column will be correctly
+// added to visits table during migration to version 40.
+TEST_F(HistoryBackendDBTest, MigrateVisitsWithoutIncrementedOmniboxTypedScore) {
+ ASSERT_NO_FATAL_FAILURE(CreateDBVersion(39));
+
+ const VisitID visit_id1 = 1;
+ const VisitID visit_id2 = 2;
+ const URLID url_id1 = 3;
+ const URLID url_id2 = 4;
+ const base::Time visit_time1(base::Time::Now());
+ const base::Time visit_time2(base::Time::Now());
+ const VisitID referring_visit1 = 0;
+ const VisitID referring_visit2 = 0;
+ const ui::PageTransition transition1 = ui::PAGE_TRANSITION_LINK;
+ const ui::PageTransition transition2 = ui::PAGE_TRANSITION_TYPED;
+ const SegmentID segment_id1 = 7;
+ const SegmentID segment_id2 = 8;
+ const base::TimeDelta visit_duration1(base::TimeDelta::FromSeconds(30));
+ const base::TimeDelta visit_duration2(base::TimeDelta::FromSeconds(45));
+
+ const char kInsertStatement[] =
+ "INSERT INTO visits "
+ "(id, url, visit_time, from_visit, transition, segment_id, "
+ "visit_duration) VALUES (?, ?, ?, ?, ?, ?, ?)";
+
+ {
+ // Open the db for manual manipulation.
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename)));
+
+ // Add entries to visits.
+ {
+ sql::Statement s(db.GetUniqueStatement(kInsertStatement));
+ s.BindInt64(0, visit_id1);
+ s.BindInt64(1, url_id1);
+ s.BindInt64(2, visit_time1.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ s.BindInt64(3, referring_visit1);
+ s.BindInt64(4, transition1);
+ s.BindInt64(5, segment_id1);
+ s.BindInt64(6, visit_duration1.InMicroseconds());
+ ASSERT_TRUE(s.Run());
+ }
+ {
+ sql::Statement s(db.GetUniqueStatement(kInsertStatement));
+ s.BindInt64(0, visit_id2);
+ s.BindInt64(1, url_id2);
+ s.BindInt64(2, visit_time2.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ s.BindInt64(3, referring_visit2);
+ s.BindInt64(4, transition2);
+ s.BindInt64(5, segment_id2);
+ s.BindInt64(6, visit_duration2.InMicroseconds());
+ ASSERT_TRUE(s.Run());
+ }
+ }
+
+ // Re-open the db, triggering migration.
+ CreateBackendAndDatabase();
+
+ VisitRow visit_row1;
+ db_->GetRowForVisit(visit_id1, &visit_row1);
+ EXPECT_FALSE(visit_row1.incremented_omnibox_typed_score);
+
+ VisitRow visit_row2;
+ db_->GetRowForVisit(visit_id2, &visit_row2);
+ EXPECT_TRUE(visit_row2.incremented_omnibox_typed_score);
+}
+
+// Tests that the migration code correctly handles rows in the visit database
+// that may be in an invalid state where visit_id == referring_visit. Regression
+// test for https://crbug.com/847246.
+TEST_F(HistoryBackendDBTest,
+ MigrateVisitsWithoutIncrementedOmniboxTypedScore_BadRow) {
+ ASSERT_NO_FATAL_FAILURE(CreateDBVersion(39));
+
+ const VisitID visit_id = 1;
+ const URLID url_id = 2;
+ const base::Time visit_time(base::Time::Now());
+ // visit_id == referring_visit will trigger DCHECK_NE in UpdateVisitRow.
+ const VisitID referring_visit = 1;
+ const ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
+ const SegmentID segment_id = 8;
+ const base::TimeDelta visit_duration(base::TimeDelta::FromSeconds(45));
+
+ const char kInsertStatement[] =
+ "INSERT INTO visits "
+ "(id, url, visit_time, from_visit, transition, segment_id, "
+ "visit_duration) VALUES (?, ?, ?, ?, ?, ?, ?)";
+
+ {
+ // Open the db for manual manipulation.
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename)));
+
+ // Add entry to visits.
+ sql::Statement s(db.GetUniqueStatement(kInsertStatement));
+ s.BindInt64(0, visit_id);
+ s.BindInt64(1, url_id);
+ s.BindInt64(2, visit_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ s.BindInt64(3, referring_visit);
+ s.BindInt64(4, transition);
+ s.BindInt64(5, segment_id);
+ s.BindInt64(6, visit_duration.InMicroseconds());
+ ASSERT_TRUE(s.Run());
+ }
+
+ // Re-open the db, triggering migration.
+ CreateBackendAndDatabase();
+
+ // Field should be false since the migration won't update it from the default
+ // due to the invalid state of the row.
+ VisitRow visit_row;
+ db_->GetRowForVisit(visit_id, &visit_row);
+ EXPECT_FALSE(visit_row.incremented_omnibox_typed_score);
+}
+
bool FilterURL(const GURL& url) {
return url.SchemeIsHTTPOrHTTPS();
}
diff --git a/chromium/components/history/core/browser/history_backend_notifier.h b/chromium/components/history/core/browser/history_backend_notifier.h
index 668185016ec..9ede9c0b49e 100644
--- a/chromium/components/history/core/browser/history_backend_notifier.h
+++ b/chromium/components/history/core/browser/history_backend_notifier.h
@@ -40,17 +40,9 @@ class HistoryBackendNotifier {
virtual void NotifyURLsModified(const URLRows& changed_urls) = 0;
// Sends notification that some or the totality of the URLs have been
- // deleted. If time_range.IsValid() is true, all URLs between
- // time_range.begin() and time_range.end() have been removed.
- // If time_range.IsAllTime() is true, then all the URLs in the
- // history have been deleted, otherwise |deleted_urls| list the deleted URLs.
- // If the URL deletion is due to expiration, then |expired| is true.
- // |favicon_urls| is the list of favicon URLs that correspond to the deleted
- // URLs (empty if |time_range.IsAllTime()| is true).
- virtual void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_urls,
- const std::set<GURL>& favicon_urls) = 0;
+ // deleted.
+ // |deletion_info| describes the urls that have been removed from history.
+ virtual void NotifyURLsDeleted(DeletionInfo deletion_info) = 0;
};
} // namespace history
diff --git a/chromium/components/history/core/browser/history_backend_unittest.cc b/chromium/components/history/core/browser/history_backend_unittest.cc
index e1eb945adff..93859a28f9b 100644
--- a/chromium/components/history/core/browser/history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_unittest.cc
@@ -137,10 +137,7 @@ class HistoryBackendTestDelegate : public HistoryBackend::Delegate {
const RedirectList& redirects,
base::Time visit_time) override;
void NotifyURLsModified(const URLRows& changed_urls) override;
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override;
+ void NotifyURLsDeleted(DeletionInfo deletion_info) override;
void NotifyKeywordSearchTermUpdated(const URLRow& row,
KeywordID keyword_id,
const base::string16& term) override;
@@ -228,14 +225,10 @@ class HistoryBackendTestBase : public testing::Test {
urls_modified_notifications_.push_back(changed_urls);
}
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
- mem_backend_->OnURLsDeleted(nullptr, time_range.IsAllTime(), expired,
- deleted_rows, favicon_urls);
- urls_deleted_notifications_.push_back(
- std::make_pair(time_range.IsAllTime(), expired));
+ void NotifyURLsDeleted(DeletionInfo deletion_info) {
+ mem_backend_->OnURLsDeleted(nullptr, deletion_info);
+ urls_deleted_notifications_.push_back(std::make_pair(
+ deletion_info.IsAllHistory(), deletion_info.is_from_expiration()));
}
void NotifyKeywordSearchTermUpdated(const URLRow& row,
@@ -268,7 +261,7 @@ class HistoryBackendTestBase : public testing::Test {
}
void TearDown() override {
- if (backend_.get())
+ if (backend_)
backend_->Closing();
backend_ = nullptr;
mem_backend_.reset();
@@ -317,12 +310,8 @@ void HistoryBackendTestDelegate::NotifyURLsModified(
test_->NotifyURLsModified(changed_urls);
}
-void HistoryBackendTestDelegate::NotifyURLsDeleted(
- const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
- test_->NotifyURLsDeleted(time_range, expired, deleted_rows, favicon_urls);
+void HistoryBackendTestDelegate::NotifyURLsDeleted(DeletionInfo deletion_info) {
+ test_->NotifyURLsDeleted(std::move(deletion_info));
}
void HistoryBackendTestDelegate::NotifyKeywordSearchTermUpdated(
@@ -502,8 +491,7 @@ class InMemoryHistoryBackendTest : public HistoryBackendTestBase {
if (row2) rows.push_back(*row2);
if (row3) rows.push_back(*row3);
- NotifyURLsDeleted(DeletionTimeRange::Invalid(), false, rows,
- std::set<GURL>());
+ NotifyURLsDeleted(DeletionInfo::ForUrls(rows, std::set<GURL>()));
}
size_t GetNumberOfMatchingSearchTerms(const int keyword_id,
@@ -2539,7 +2527,7 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationNewFavicon) {
backend_->SetFavicons({page_url1}, IconType::kFavicon, 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());
+ EXPECT_EQ(1u, favicon_changed_notifications_icon_urls().size());
ClearBroadcastedNotifications();
}
@@ -2553,7 +2541,7 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationNewFavicon) {
bitmap_data, kSmallSize);
ASSERT_EQ(1u, favicon_changed_notifications_page_urls().size());
EXPECT_EQ(page_url2, favicon_changed_notifications_page_urls()[0]);
- EXPECT_EQ(0u, favicon_changed_notifications_icon_urls().size());
+ EXPECT_EQ(1u, favicon_changed_notifications_icon_urls().size());
}
}
@@ -3870,6 +3858,28 @@ TEST_F(HistoryBackendTest, DatabaseError) {
base::RunLoop().RunUntilIdle();
}
+// Tests that calling DatabaseErrorCallback results in killing the database and
+// notifying the TypedURLSyncBridge at the same time so that no further
+// notification from the backend can lead to the bridge. (Regression test for
+// https://crbug.com/853395)
+TEST_F(HistoryBackendTest, DatabaseErrorSynchronouslyKillAndNotifyBridge) {
+ // Notify the backend that a database error occurred.
+ backend_->DatabaseErrorCallback(SQLITE_CORRUPT, nullptr);
+ // In-between (before the posted task finishes), we can again delete all
+ // history.
+ backend_->ExpireHistoryBetween(/*restrict_urls=*/std::set<GURL>(),
+ /*begin_time=*/base::Time(),
+ /*end_time=*/base::Time::Max());
+
+ // Run loop to let the posted task to kill the DB run.
+ base::RunLoop().RunUntilIdle();
+ // After DB is destroyed, we can again try to delete all history (with no
+ // effect but it should not crash).
+ backend_->ExpireHistoryBetween(/*restrict_urls=*/std::set<GURL>(),
+ /*begin_time=*/base::Time(),
+ /*end_time=*/base::Time::Max());
+}
+
// Common implementation for the two tests below, given that the only difference
// between them is the type of the notification sent out.
void InMemoryHistoryBackendTest::TestAddingAndChangingURLRows(
@@ -3955,8 +3965,7 @@ TEST_F(InMemoryHistoryBackendTest, OnURLsDeletedEnMasse) {
SimulateNotificationURLsModified(mem_backend_.get(), &row1, &row2, &row3);
// Now notify the in-memory database that all history has been deleted.
- mem_backend_->OnURLsDeleted(nullptr, true, false, URLRows(),
- std::set<GURL>());
+ mem_backend_->OnURLsDeleted(nullptr, history::DeletionInfo::ForAllHistory());
// Expect that everything goes away.
EXPECT_EQ(0, mem_backend_->db()->GetRowForURL(row1.url(), nullptr));
diff --git a/chromium/components/history/core/browser/history_constants.cc b/chromium/components/history/core/browser/history_constants.cc
index 79cd33fa6e0..d657062d4d8 100644
--- a/chromium/components/history/core/browser/history_constants.cc
+++ b/chromium/components/history/core/browser/history_constants.cc
@@ -18,6 +18,8 @@ const base::FilePath::CharType kTopSitesFilename[] =
const int kMaxTopHosts = 50;
+const int kMaxTitleChanges = 10;
+
base::TimeDelta GetTitleSettingWindow() {
const auto value = base::TimeDelta::FromSeconds(5);
return value;
diff --git a/chromium/components/history/core/browser/history_constants.h b/chromium/components/history/core/browser/history_constants.h
index b89804c49c3..1f3d88896da 100644
--- a/chromium/components/history/core/browser/history_constants.h
+++ b/chromium/components/history/core/browser/history_constants.h
@@ -18,6 +18,11 @@ extern const base::FilePath::CharType kTopSitesFilename[];
// The maximum size of the list returned by history::HistoryService::TopHosts().
extern const int kMaxTopHosts;
+// The maximum number of times a page can change it's title during the relevant
+// timestamp (page is either loading is has recently loaded as per
+// GetTitleSettingWindow() below).
+extern const int kMaxTitleChanges;
+
// The span of time after load is complete during which a page may set its title
// and have the title change be saved in history.
base::TimeDelta GetTitleSettingWindow();
diff --git a/chromium/components/history/core/browser/history_database.cc b/chromium/components/history/core/browser/history_database.cc
index 2a983559f11..d80bc2395a4 100644
--- a/chromium/components/history/core/browser/history_database.cc
+++ b/chromium/components/history/core/browser/history_database.cc
@@ -38,7 +38,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 = 39;
+const int kCurrentVersionNumber = 40;
const int kCompatibleVersionNumber = 16;
const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
const int kMaxHostsInMemory = 10000;
@@ -600,6 +600,13 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
meta_table_.SetVersionNumber(cur_version);
}
+ if (cur_version == 39) {
+ if (!MigrateVisitsWithoutIncrementedOmniboxTypedScore())
+ return LogMigrationFailure(39);
+ 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_database_params.cc b/chromium/components/history/core/browser/history_database_params.cc
index 3f02563a42a..ccc6983de91 100644
--- a/chromium/components/history/core/browser/history_database_params.cc
+++ b/chromium/components/history/core/browser/history_database_params.cc
@@ -7,10 +7,7 @@
namespace history {
HistoryDatabaseParams::HistoryDatabaseParams()
- : history_dir(),
- download_interrupt_reason_none(0),
- download_interrupt_reason_crash(0) {
-}
+ : download_interrupt_reason_none(0), download_interrupt_reason_crash(0) {}
HistoryDatabaseParams::HistoryDatabaseParams(
const base::FilePath& history_dir,
diff --git a/chromium/components/history/core/browser/history_model_worker.cc b/chromium/components/history/core/browser/history_model_worker.cc
index ed8a970f4b5..c68b377ea50 100644
--- a/chromium/components/history/core/browser/history_model_worker.cc
+++ b/chromium/components/history/core/browser/history_model_worker.cc
@@ -42,7 +42,7 @@ void PostWorkerTask(
const base::WeakPtr<history::HistoryService>& history_service,
base::OnceClosure work,
base::CancelableTaskTracker* cancelable_tracker) {
- if (history_service.get()) {
+ if (history_service) {
history_service->ScheduleDBTask(
FROM_HERE, std::make_unique<WorkerTask>(std::move(work)),
cancelable_tracker);
@@ -62,7 +62,7 @@ HistoryModelWorker::HistoryModelWorker(
// constructed and deleted on the same sequence.
cancelable_tracker_(new base::CancelableTaskTracker,
base::OnTaskRunnerDeleter(ui_thread_)) {
- CHECK(history_service.get());
+ CHECK(history_service);
DCHECK(ui_thread_->BelongsToCurrentThread());
}
diff --git a/chromium/components/history/core/browser/history_querying_unittest.cc b/chromium/components/history/core/browser/history_querying_unittest.cc
index fede4e3f9e6..04f821b90e4 100644
--- a/chromium/components/history/core/browser/history_querying_unittest.cc
+++ b/chromium/components/history/core/browser/history_querying_unittest.cc
@@ -183,7 +183,7 @@ class HistoryQueryTest : public testing::Test {
void TearDown() override {
if (history_) {
history_->SetOnBackendDestroyTask(
- base::MessageLoop::QuitWhenIdleClosure());
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
history_->Cleanup();
history_.reset();
base::RunLoop().Run(); // Wait for the other thread.
diff --git a/chromium/components/history/core/browser/history_service.cc b/chromium/components/history/core/browser/history_service.cc
index d10919a3946..2f4975b203b 100644
--- a/chromium/components/history/core/browser/history_service.cc
+++ b/chromium/components/history/core/browser/history_service.cc
@@ -152,14 +152,10 @@ class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
history_service_, changed_urls));
}
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override {
+ void NotifyURLsDeleted(DeletionInfo deletion_info) override {
service_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&HistoryService::NotifyURLsDeleted, history_service_,
- time_range, expired, deleted_rows, favicon_urls));
+ FROM_HERE, base::BindOnce(&HistoryService::NotifyURLsDeleted,
+ history_service_, std::move(deletion_info)));
}
void NotifyKeywordSearchTermUpdated(const URLRow& row,
@@ -344,7 +340,7 @@ void HistoryService::TopHosts(size_t num_hosts,
callback);
}
-void HistoryService::GetCountsAndLastVisitForOrigins(
+void HistoryService::GetCountsAndLastVisitForOriginsForTesting(
const std::set<GURL>& origins,
const GetCountsAndLastVisitForOriginsCallback& callback) const {
DCHECK(backend_task_runner_) << "History service being called after cleanup";
@@ -903,7 +899,7 @@ void HistoryService::Cleanup() {
history_client_->Shutdown();
// Unload the backend.
- if (history_backend_.get()) {
+ if (history_backend_) {
// Get rid of the in-memory backend.
in_memory_backend_.reset();
@@ -1109,6 +1105,19 @@ void HistoryService::ExpireHistory(
callback);
}
+void HistoryService::ExpireHistoryBeforeForTesting(
+ base::Time end_time,
+ base::OnceClosure callback,
+ base::CancelableTaskTracker* tracker) {
+ DCHECK(backend_task_runner_) << "History service being called after cleanup";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ tracker->PostTaskAndReply(
+ backend_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&HistoryBackend::ExpireHistoryBeforeForTesting,
+ history_backend_, end_time),
+ std::move(callback));
+}
+
void HistoryService::ExpireLocalAndRemoteHistoryBetween(
WebHistoryService* web_history,
const std::set<GURL>& restrict_urls,
@@ -1182,12 +1191,8 @@ void HistoryService::NotifyURLsModified(const URLRows& changed_urls) {
observer.OnURLsModified(this, changed_urls);
}
-void HistoryService::NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
+void HistoryService::NotifyURLsDeleted(const DeletionInfo& deletion_info) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!time_range.IsAllTime() || deleted_rows.empty());
if (!backend_task_runner_)
return;
@@ -1200,23 +1205,19 @@ void HistoryService::NotifyURLsDeleted(const DeletionTimeRange& time_range,
// respectful of privacy and never tell the user something is gone when it
// isn't. Therefore, we update the delete URLs after the fact.
if (visit_delegate_) {
- if (time_range.IsAllTime()) {
+ if (deletion_info.IsAllHistory()) {
visit_delegate_->DeleteAllURLs();
} else {
std::vector<GURL> urls;
- urls.reserve(deleted_rows.size());
- for (const auto& row : deleted_rows)
+ urls.reserve(deletion_info.deleted_rows().size());
+ for (const auto& row : deletion_info.deleted_rows())
urls.push_back(row.url());
visit_delegate_->DeleteURLs(urls);
}
}
- for (HistoryServiceObserver& observer : observers_) {
- observer.OnURLsDeleted(this, time_range.IsAllTime(), expired, deleted_rows,
- favicon_urls);
- observer.OnURLsDeleted(this, time_range, expired, deleted_rows,
- favicon_urls);
- }
+ for (HistoryServiceObserver& observer : observers_)
+ observer.OnURLsDeleted(this, deletion_info);
}
void HistoryService::NotifyHistoryServiceLoaded() {
diff --git a/chromium/components/history/core/browser/history_service.h b/chromium/components/history/core/browser/history_service.h
index d0e1a2805fb..6c4aeb6904e 100644
--- a/chromium/components/history/core/browser/history_service.h
+++ b/chromium/components/history/core/browser/history_service.h
@@ -161,7 +161,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
// Gets the counts and most recent visit date of URLs that belong to |origins|
// in the history database.
- void GetCountsAndLastVisitForOrigins(
+ void GetCountsAndLastVisitForOriginsForTesting(
const std::set<GURL>& origins,
const GetCountsAndLastVisitForOriginsCallback& callback) const;
@@ -371,6 +371,12 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
const base::Closure& callback,
base::CancelableTaskTracker* tracker);
+ // Expires all visits before and including the given time, updating the URLs
+ // accordingly.
+ void ExpireHistoryBeforeForTesting(base::Time end_time,
+ base::OnceClosure callback,
+ base::CancelableTaskTracker* tracker);
+
// Removes all visits to the given URLs in the specified time range. Calls
// ExpireHistoryBetween() to delete local visits, and handles deletion of
// synced visits if appropriate.
@@ -605,16 +611,8 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
void NotifyURLsModified(const URLRows& changed_urls);
// Notify all HistoryServiceObservers registered that URLs have been deleted.
- // |all_history| is set to true, if all the URLs are deleted.
- // When set to true, |deleted_rows| and |favicon_urls| are
- // undefined.
- // |expired| is set to true, if the URL deletion is due to expiration.
- // |deleted_rows| list of the deleted URLs.
- // |favicon_urls| list of favicon URLs that correspond to the deleted URLs.
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls);
+ // |deletion_info| describes the urls that have been removed from history.
+ void NotifyURLsDeleted(const DeletionInfo& deletion_info);
// Notify all HistoryServiceObservers registered that the
// HistoryService has finished loading.
diff --git a/chromium/components/history/core/browser/history_service_observer.h b/chromium/components/history/core/browser/history_service_observer.h
index 3220ce56e47..e0809335a49 100644
--- a/chromium/components/history/core/browser/history_service_observer.h
+++ b/chromium/components/history/core/browser/history_service_observer.h
@@ -39,36 +39,11 @@ class HistoryServiceObserver {
virtual void OnURLsModified(HistoryService* history_service,
const URLRows& changed_urls) {}
- // Called when one or more of URLs are deleted.
+ // Called when one or more URLs are deleted.
//
- // |all_history| is set to true, if all the URLs are deleted.
- // When set to true, |deleted_rows| and |favicon_urls| are
- // undefined.
- // |expired| is set to true, if the URL deletion is due to expiration.
- // |deleted_rows| list of the deleted URLs.
- // |favicon_urls| list of favicon URLs that correspond to the deleted URLs.
- // DEPRECATED, use OnURLsDeleted() with |time_range| parameter.
- // TODO(dullweber): Migrate observers to new OnURLsDeleted() method.
+ // |deletion_info| describes the urls that have been removed from history.
virtual void OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {}
-
- // Called when one or more of URLs are deleted.
- //
- // |time_range| If time_range.IsValid() is true, all URLs between
- // time_range.begin() and time_range.end() have been removed.
- // If time_range.IsAllTime() is true, all URLs are deleted and
- // |deleted_rows| and |favicon_urls| are undefined.
- // |expired| is set to true, if the URL deletion is due to expiration.
- // |deleted_rows| list of the deleted URLs.
- // |favicon_urls| list of favicon URLs that correspond to the deleted URLs.
- virtual void OnURLsDeleted(HistoryService* history_service,
- const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {}
+ const DeletionInfo& deletion_info) {}
// Is called to notify when |history_service| has finished loading.
virtual void OnHistoryServiceLoaded(HistoryService* history_service) {}
diff --git a/chromium/components/history/core/browser/history_service_unittest.cc b/chromium/components/history/core/browser/history_service_unittest.cc
index 4ed089e1f4a..eb65c9ab1c3 100644
--- a/chromium/components/history/core/browser/history_service_unittest.cc
+++ b/chromium/components/history/core/browser/history_service_unittest.cc
@@ -25,7 +25,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -85,7 +84,7 @@ class HistoryServiceTest : public testing::Test {
// Make sure we don't have any event pending that could disrupt the next
// test.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
base::RunLoop().Run();
}
@@ -94,7 +93,7 @@ class HistoryServiceTest : public testing::Test {
history_service_->ClearCachedDataForContextID(nullptr);
history_service_->SetOnBackendDestroyTask(
- base::MessageLoop::QuitWhenIdleClosure());
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
history_service_->Cleanup();
history_service_.reset();
diff --git a/chromium/components/history/core/browser/history_types.cc b/chromium/components/history/core/browser/history_types.cc
index ffbbff03376..67263b5344c 100644
--- a/chromium/components/history/core/browser/history_types.cc
+++ b/chromium/components/history/core/browser/history_types.cc
@@ -20,12 +20,14 @@ VisitRow::VisitRow(URLID arg_url_id,
base::Time arg_visit_time,
VisitID arg_referring_visit,
ui::PageTransition arg_transition,
- SegmentID arg_segment_id)
+ SegmentID arg_segment_id,
+ bool arg_incremented_omnibox_typed_score)
: url_id(arg_url_id),
visit_time(arg_visit_time),
referring_visit(arg_referring_visit),
transition(arg_transition),
- segment_id(arg_segment_id) {}
+ segment_id(arg_segment_id),
+ incremented_omnibox_typed_score(arg_incremented_omnibox_typed_score) {}
VisitRow::~VisitRow() {
}
@@ -369,4 +371,44 @@ bool DeletionTimeRange::IsAllTime() const {
return begin_.is_null() && (end_.is_null() || end_.is_max());
}
+// DeletionInfo
+// ----------------------------------------------------------
+
+// static
+DeletionInfo DeletionInfo::ForAllHistory() {
+ return DeletionInfo(DeletionTimeRange::AllTime(), false, {}, {},
+ base::nullopt);
+}
+
+// static
+DeletionInfo DeletionInfo::ForUrls(URLRows deleted_rows,
+ std::set<GURL> favicon_urls) {
+ return DeletionInfo(DeletionTimeRange::Invalid(), false,
+ std::move(deleted_rows), std::move(favicon_urls),
+ base::nullopt);
+}
+
+DeletionInfo::DeletionInfo(const DeletionTimeRange& time_range,
+ bool is_from_expiration,
+ URLRows deleted_rows,
+ std::set<GURL> favicon_urls,
+ base::Optional<std::set<GURL>> restrict_urls)
+ : time_range_(time_range),
+ is_from_expiration_(is_from_expiration),
+ deleted_rows_(std::move(deleted_rows)),
+ favicon_urls_(std::move(favicon_urls)),
+ restrict_urls_(std::move(restrict_urls)) {
+ // If time_range is all time or invalid, restrict_urls should be empty.
+ DCHECK(!time_range_.IsAllTime() || !restrict_urls_.has_value());
+ DCHECK(time_range_.IsValid() || !restrict_urls_.has_value());
+ // If restrict_urls_ is defined, it should be non-empty.
+ DCHECK(!restrict_urls_.has_value() || !restrict_urls_->empty());
+};
+
+DeletionInfo::~DeletionInfo() = default;
+
+DeletionInfo::DeletionInfo(DeletionInfo&& other) noexcept = default;
+
+DeletionInfo& DeletionInfo::operator=(DeletionInfo&& rhs) noexcept = default;
+
} // namespace history
diff --git a/chromium/components/history/core/browser/history_types.h b/chromium/components/history/core/browser/history_types.h
index ff27b0d7406..5e72a015705 100644
--- a/chromium/components/history/core/browser/history_types.h
+++ b/chromium/components/history/core/browser/history_types.h
@@ -17,6 +17,7 @@
#include "base/containers/stack_container.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "components/favicon_base/favicon_types.h"
@@ -72,7 +73,8 @@ class VisitRow {
base::Time arg_visit_time,
VisitID arg_referring_visit,
ui::PageTransition arg_transition,
- SegmentID arg_segment_id);
+ SegmentID arg_segment_id,
+ bool arg_incremented_omnibox_typed_score);
~VisitRow();
// ID of this row (visit ID, used a a referrer for other visits).
@@ -100,6 +102,9 @@ class VisitRow {
// the visit was present.
base::TimeDelta visit_duration;
+ // Records whether the visit incremented the omnibox typed score.
+ bool incremented_omnibox_typed_score = false;
+
// Compares two visits based on dates, for sorting.
bool operator<(const VisitRow& other) const {
return visit_time < other.visit_time;
@@ -622,6 +627,97 @@ class DeletionTimeRange {
base::Time end_;
};
+// Describes the urls that have been removed due to a history deletion.
+// If |IsAllHistory()| returns true, all urls haven been deleted.
+// In this case, |deleted_rows()| and |favicon_urls()| are undefined.
+// Otherwise |deleted_rows()| contains the urls where all visits have been
+// removed from history.
+// If |expired()| returns true, this deletion is due to a regularly performed
+// history expiration. Otherwise it is an explicit deletion due to a user
+// action.
+class DeletionInfo {
+ public:
+ // Returns a DeletionInfo that covers all history.
+ static DeletionInfo ForAllHistory();
+ // Returns a DeletionInfo with invalid time range for the given urls.
+ static DeletionInfo ForUrls(URLRows deleted_rows,
+ std::set<GURL> favicon_urls);
+
+ DeletionInfo(const DeletionTimeRange& time_range,
+ bool is_from_expiration,
+ URLRows deleted_rows,
+ std::set<GURL> favicon_urls,
+ base::Optional<std::set<GURL>> restrict_urls);
+
+ ~DeletionInfo();
+ // Move-only because of potentially large containers.
+ DeletionInfo(DeletionInfo&& other) noexcept;
+ DeletionInfo& operator=(DeletionInfo&& rhs) noexcept;
+
+ // If IsAllHistory() returns true, all URLs are deleted and |deleted_rows()|
+ // and |favicon_urls()| are undefined.
+ bool IsAllHistory() const { return time_range_.IsAllTime(); }
+
+ // If time_range.IsValid() is true, |restrict_urls| (or all URLs if empty)
+ // between time_range.begin() and time_range.end() have been removed.
+ const DeletionTimeRange& time_range() const { return time_range_; }
+
+ // Restricts deletions within |time_range()|.
+ const base::Optional<std::set<GURL>>& restrict_urls() const {
+ return restrict_urls_;
+ }
+
+ // Returns true, if the URL deletion is due to expiration.
+ bool is_from_expiration() const { return is_from_expiration_; }
+
+ // Returns the list of the deleted URLs.
+ // Undefined if |IsAllHistory()| returns true.
+ const URLRows& deleted_rows() const { return deleted_rows_; }
+
+ // Returns the list of favicon URLs that correspond to the deleted URLs.
+ // Undefined if |IsAllHistory()| returns true.
+ const std::set<GURL>& favicon_urls() const { return favicon_urls_; }
+
+ // Returns a map from origins with deleted urls to a count of remaining URLs
+ // and the last visited time.
+ const OriginCountAndLastVisitMap& deleted_urls_origin_map() const {
+ // The map should only be accessed after it has been populated.
+ DCHECK(deleted_rows_.empty() || !deleted_urls_origin_map_.empty());
+ return deleted_urls_origin_map_;
+ }
+
+ // Populates deleted_urls_origin_map.
+ void set_deleted_urls_origin_map(OriginCountAndLastVisitMap origin_map) {
+ DCHECK(deleted_urls_origin_map_.empty());
+ deleted_urls_origin_map_ = std::move(origin_map);
+ }
+
+ private:
+ DeletionTimeRange time_range_;
+ bool is_from_expiration_;
+ URLRows deleted_rows_;
+ std::set<GURL> favicon_urls_;
+ base::Optional<std::set<GURL>> restrict_urls_;
+ OriginCountAndLastVisitMap deleted_urls_origin_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeletionInfo);
+};
+
+// Represents a visit to a domain.
+class DomainVisit {
+ public:
+ DomainVisit(const std::string& domain, base::Time visit_time)
+ : domain_(domain), visit_time_(visit_time) {}
+
+ const std::string& domain() const { return domain_; }
+
+ const base::Time visit_time() const { return visit_time_; }
+
+ private:
+ std::string domain_;
+ base::Time visit_time_;
+};
+
} // namespace history
#endif // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_TYPES_H_
diff --git a/chromium/components/history/core/browser/in_memory_database.cc b/chromium/components/history/core/browser/in_memory_database.cc
index 3ae5f679041..dfac5c5e125 100644
--- a/chromium/components/history/core/browser/in_memory_database.cc
+++ b/chromium/components/history/core/browser/in_memory_database.cc
@@ -13,8 +13,7 @@
namespace history {
-InMemoryDatabase::InMemoryDatabase() : URLDatabase() {
-}
+InMemoryDatabase::InMemoryDatabase() {}
InMemoryDatabase::~InMemoryDatabase() {
}
diff --git a/chromium/components/history/core/browser/in_memory_history_backend.cc b/chromium/components/history/core/browser/in_memory_history_backend.cc
index 9e11553e1ea..8384e6b5671 100644
--- a/chromium/components/history/core/browser/in_memory_history_backend.cc
+++ b/chromium/components/history/core/browser/in_memory_history_backend.cc
@@ -58,13 +58,10 @@ void InMemoryHistoryBackend::OnURLsModified(HistoryService* history_service,
}
void InMemoryHistoryBackend::OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
+ const DeletionInfo& deletion_info) {
DCHECK(db_);
- if (all_history) {
+ if (deletion_info.IsAllHistory()) {
// When all history is deleted, the individual URLs won't be listed. Just
// create a new database to quickly clear everything out.
db_.reset(new InMemoryDatabase);
@@ -74,7 +71,7 @@ void InMemoryHistoryBackend::OnURLsDeleted(HistoryService* history_service,
}
// Delete all matching URLs in our database.
- for (const auto& row : deleted_rows) {
+ for (const auto& row : deletion_info.deleted_rows()) {
// This will also delete the corresponding keyword search term.
// Ignore errors, as we typically only cache a subset of URLRows.
db_->DeleteURLRow(row.id());
diff --git a/chromium/components/history/core/browser/in_memory_history_backend.h b/chromium/components/history/core/browser/in_memory_history_backend.h
index 2462543c512..557467dc99c 100644
--- a/chromium/components/history/core/browser/in_memory_history_backend.h
+++ b/chromium/components/history/core/browser/in_memory_history_backend.h
@@ -78,10 +78,7 @@ class InMemoryHistoryBackend : public HistoryServiceObserver {
void OnURLsModified(HistoryService* history_service,
const URLRows& changed_urls) override;
void OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override;
+ const DeletionInfo& deletion_info) override;
void OnKeywordSearchTermUpdated(HistoryService* history_service,
const URLRow& row,
KeywordID keyword_id,
diff --git a/chromium/components/history/core/browser/thumbnail_database_unittest.cc b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
index 4a3f3d793bd..8555de8676f 100644
--- a/chromium/components/history/core/browser/thumbnail_database_unittest.cc
+++ b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
@@ -928,7 +928,7 @@ TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
// Test loading version 3 database.
TEST_F(ThumbnailDatabaseTest, Version3) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v3.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
// Version 3 is deprecated, the data should all be gone.
@@ -938,7 +938,7 @@ TEST_F(ThumbnailDatabaseTest, Version3) {
// Test loading version 4 database.
TEST_F(ThumbnailDatabaseTest, Version4) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v4.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
// Version 4 is deprecated, the data should all be gone.
@@ -948,7 +948,7 @@ TEST_F(ThumbnailDatabaseTest, Version4) {
// Test loading version 5 database.
TEST_F(ThumbnailDatabaseTest, Version5) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v5.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
// Version 5 is deprecated, the data should all be gone.
@@ -958,7 +958,7 @@ TEST_F(ThumbnailDatabaseTest, Version5) {
// Test loading version 6 database.
TEST_F(ThumbnailDatabaseTest, Version6) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v6.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
// Version 6 is deprecated, the data should all be gone.
@@ -968,7 +968,7 @@ TEST_F(ThumbnailDatabaseTest, Version6) {
// Test loading version 7 database.
TEST_F(ThumbnailDatabaseTest, Version7) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v7.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1,
@@ -988,7 +988,7 @@ TEST_F(ThumbnailDatabaseTest, Version7) {
// Test loading version 8 database.
TEST_F(ThumbnailDatabaseTest, Version8) {
std::unique_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v8.sql");
- ASSERT_TRUE(db.get() != nullptr);
+ ASSERT_TRUE(db);
VerifyTablesAndColumns(&db->db_);
EXPECT_TRUE(CheckPageHasIcon(db.get(), kPageUrl1,
diff --git a/chromium/components/history/core/browser/top_sites.cc b/chromium/components/history/core/browser/top_sites.cc
index 5acf6dbf218..c24bacbf1ee 100644
--- a/chromium/components/history/core/browser/top_sites.cc
+++ b/chromium/components/history/core/browser/top_sites.cc
@@ -9,8 +9,7 @@
namespace history {
PrepopulatedPage::PrepopulatedPage()
- : most_visited(), favicon_id(-1), thumbnail_id(-1), color() {
-}
+ : favicon_id(-1), thumbnail_id(-1), color() {}
PrepopulatedPage::PrepopulatedPage(const GURL& url,
const base::string16& title,
diff --git a/chromium/components/history/core/browser/top_sites_impl.cc b/chromium/components/history/core/browser/top_sites_impl.cc
index 0ed5797f860..eba874f4c99 100644
--- a/chromium/components/history/core/browser/top_sites_impl.cc
+++ b/chromium/components/history/core/browser/top_sites_impl.cc
@@ -890,19 +890,16 @@ void TopSitesImpl::OnTopSitesAvailableFromHistory(
}
void TopSitesImpl::OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
+ const DeletionInfo& deletion_info) {
if (!loaded_)
return;
- if (all_history) {
+ if (deletion_info.IsAllHistory()) {
SetTopSites(MostVisitedURLList(), CALL_LOCATION_FROM_OTHER_PLACES);
backend_->ResetDatabase();
} else {
std::set<size_t> indices_to_delete; // Indices into top_sites_.
- for (const auto& row : deleted_rows) {
+ for (const auto& row : deletion_info.deleted_rows()) {
if (cache_->IsKnownURL(row.url()))
indices_to_delete.insert(cache_->GetURLIndex(row.url()));
}
diff --git a/chromium/components/history/core/browser/top_sites_impl.h b/chromium/components/history/core/browser/top_sites_impl.h
index dc40668f6d1..ea6751b3fb3 100644
--- a/chromium/components/history/core/browser/top_sites_impl.h
+++ b/chromium/components/history/core/browser/top_sites_impl.h
@@ -268,10 +268,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// history::HistoryServiceObserver:
void OnURLsDeleted(HistoryService* history_service,
- bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override;
+ const DeletionInfo& deletion_info) override;
// Ensures that non thread-safe methods are called on the correct thread.
base::ThreadChecker thread_checker_;
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
index 33fc6d462b4..08fa338e7bc 100644
--- a/chromium/components/history/core/browser/typed_url_model_type_controller.cc
+++ b/chromium/components/history/core/browser/typed_url_model_type_controller.cc
@@ -9,11 +9,13 @@
#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/model_type_controller.h"
#include "components/sync/driver/sync_client.h"
+#include "components/sync/model/model_type_controller_delegate.h"
using syncer::ModelType;
using syncer::ModelTypeController;
-using syncer::ModelTypeSyncBridge;
+using syncer::ModelTypeControllerDelegate;
using syncer::SyncClient;
namespace history {
@@ -25,7 +27,7 @@ namespace {
// the tasks we want to run.
class RunTaskOnHistoryThread : public HistoryDBTask {
public:
- explicit RunTaskOnHistoryThread(ModelTypeController::BridgeTask task)
+ explicit RunTaskOnHistoryThread(ModelTypeController::ModelTask task)
: task_(std::move(task)) {}
bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) override {
@@ -33,17 +35,20 @@ class RunTaskOnHistoryThread : public HistoryDBTask {
// 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.
- TypedURLSyncBridge* bridge = backend->GetTypedURLSyncBridge();
- DCHECK(bridge);
+ base::WeakPtr<ModelTypeControllerDelegate> delegate =
+ backend->GetTypedURLSyncBridge()
+ ->change_processor()
+ ->GetControllerDelegateOnUIThread();
+ DCHECK(delegate);
- std::move(task_).Run(bridge);
+ std::move(task_).Run(delegate);
return true;
}
void DoneRunOnMainThread() override {}
protected:
- ModelTypeController::BridgeTask task_;
+ ModelTypeController::ModelTask task_;
};
} // namespace
@@ -68,8 +73,8 @@ bool TypedURLModelTypeController::ReadyForStart() const {
history_disabled_pref_name_);
}
-void TypedURLModelTypeController::PostBridgeTask(const base::Location& location,
- BridgeTask task) {
+void TypedURLModelTypeController::PostModelTask(const base::Location& location,
+ ModelTask task) {
history::HistoryService* history = sync_client()->GetHistoryService();
if (!history) {
// History must be disabled - don't start.
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
index d528d409fbd..df2a43dded9 100644
--- a/chromium/components/history/core/browser/typed_url_model_type_controller.h
+++ b/chromium/components/history/core/browser/typed_url_model_type_controller.h
@@ -23,7 +23,7 @@ class TypedURLModelTypeController : public syncer::ModelTypeController {
private:
// syncer::ModelTypeController implementation.
- void PostBridgeTask(const base::Location& location, BridgeTask task) override;
+ void PostModelTask(const base::Location& location, ModelTask task) override;
void OnSavingBrowserHistoryDisabledChanged();
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 230ac721223..edbd2b4e795 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge.cc
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge.cc
@@ -281,7 +281,7 @@ void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
continue;
std::unique_ptr<syncer::EntityData> entity_data =
CreateEntityData(url_row, visits_vector);
- if (!entity_data.get()) {
+ if (!entity_data) {
// Cannot create EntityData, ex. no TYPED visits.
continue;
}
@@ -311,7 +311,7 @@ void TypedURLSyncBridge::GetAllData(DataCallback callback) {
continue;
std::unique_ptr<syncer::EntityData> entity_data =
CreateEntityData(url, visits_vector);
- if (!entity_data.get()) {
+ if (!entity_data) {
// Cannot create EntityData, ex. no TYPED visits.
continue;
}
@@ -410,8 +410,20 @@ void TypedURLSyncBridge::OnURLsDeleted(HistoryBackend* history_backend,
// client with a bad clock setting won't go on an expiration rampage and
// delete all history from every client). The server will gracefully age out
// the sync DB entries when they've been idle for long enough.
- if (expired)
+ if (expired) {
+ // Delete metadata from the DB and ask the processor to untrack the entries.
+ for (const URLRow& row : deleted_rows) {
+ std::string storage_key = GetStorageKeyFromURLRow(row);
+ sync_metadata_database_->ClearSyncMetadata(syncer::TYPED_URLS,
+ storage_key);
+ // TODO(jkrcal): Untrack the entity from the processor, too (by
+ // introducing UntrackEntityForStorageKey() function into the change
+ // processor). Extend the integration tests to cover the crash in
+ // https://crbug.com/827111. Also add unit-test coverage for expired
+ // deletions (needs some refactoring in the tests).
+ }
return;
+ }
std::unique_ptr<MetadataChangeList> metadata_change_list =
CreateMetadataChangeList();
@@ -431,7 +443,7 @@ void TypedURLSyncBridge::OnURLsDeleted(HistoryBackend* history_backend,
}
} else {
// Delete rows.
- for (const auto& row : deleted_rows) {
+ for (const URLRow& row : deleted_rows) {
std::string storage_key = GetStorageKeyFromURLRow(row);
change_processor()->Delete(storage_key, metadata_change_list.get());
}
@@ -648,8 +660,10 @@ TypedURLSyncBridge::MergeResult TypedURLSyncBridge::MergeUrls(
new_visit->first > visit_ix->visit_time) {
++visit_ix;
}
- visit_ix = visits->insert(visit_ix, VisitRow(url.id(), new_visit->first,
- 0, new_visit->second, 0));
+ visit_ix = visits->insert(
+ visit_ix,
+ VisitRow(url.id(), new_visit->first, 0, new_visit->second, 0,
+ HistoryBackend::IsTypedIncrement(new_visit->second)));
++visit_ix;
}
}
@@ -740,7 +754,7 @@ void TypedURLSyncBridge::LoadMetadata() {
"TypedURLSyncMetadataDatabase."});
return;
}
- change_processor()->ModelReadyToSync(this, std::move(batch));
+ change_processor()->ModelReadyToSync(std::move(batch));
}
void TypedURLSyncBridge::ClearErrorStats() {
@@ -1096,7 +1110,7 @@ bool TypedURLSyncBridge::FixupURLAndGetVisits(URLRow* url,
}
VisitRow visit(url->id(), url->last_visit(), 0, ui::PAGE_TRANSITION_TYPED,
- 0);
+ 0, true);
visits->push_back(visit);
}
@@ -1200,7 +1214,7 @@ void TypedURLSyncBridge::SendTypedURLToProcessor(
std::unique_ptr<syncer::EntityData> entity_data =
CreateEntityData(row, visits);
- if (!entity_data.get()) {
+ if (!entity_data) {
// Cannot create EntityData, ex. no TYPED visits.
return;
}
diff --git a/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc b/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
index d96c38b3188..6eb285e17c1 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
@@ -70,7 +70,9 @@ void AddNewestVisit(ui::PageTransition transition,
URLRow* url,
VisitVector* visits) {
base::Time time = base::Time::FromInternalValue(visit_time);
- visits->insert(visits->begin(), VisitRow(url->id(), time, 0, transition, 0));
+ visits->insert(visits->begin(),
+ VisitRow(url->id(), time, 0, transition, 0,
+ HistoryBackend::IsTypedIncrement(transition)));
if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
url->set_typed_count(url->typed_count() + 1);
@@ -85,7 +87,8 @@ void AddOldestVisit(ui::PageTransition transition,
URLRow* url,
VisitVector* visits) {
base::Time time = base::Time::FromInternalValue(visit_time);
- visits->push_back(VisitRow(url->id(), time, 0, transition, 0));
+ visits->push_back(VisitRow(url->id(), time, 0, transition, 0,
+ HistoryBackend::IsTypedIncrement(transition)));
if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
url->set_typed_count(url->typed_count() + 1);
@@ -115,11 +118,11 @@ URLRow MakeTypedUrlRow(const std::string& url,
if (typed_count > 0) {
// Add a typed visit for time |last_visit|.
visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
- ui::PAGE_TRANSITION_TYPED, 0));
+ ui::PAGE_TRANSITION_TYPED, 0, true));
} else {
// Add a non-typed visit for time |last_visit|.
visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
- ui::PAGE_TRANSITION_RELOAD, 0));
+ ui::PAGE_TRANSITION_RELOAD, 0, false));
}
history_url.set_visit_count(visits->size());
@@ -178,10 +181,7 @@ class TestHistoryBackendDelegate : public HistoryBackend::Delegate {
const RedirectList& redirects,
base::Time visit_time) override {}
void NotifyURLsModified(const URLRows& changed_urls) override {}
- void NotifyURLsDeleted(const DeletionTimeRange& time_range,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override {}
+ void NotifyURLsDeleted(DeletionInfo deletion_info) override {}
void NotifyKeywordSearchTermUpdated(const URLRow& row,
KeywordID keyword_id,
const base::string16& term) override {}
@@ -305,14 +305,15 @@ class TypedURLSyncBridgeTest : public testing::Test {
int typed_count,
int64_t last_visit,
bool hidden,
+ bool update_metadata,
EntityChange::ChangeType change_type) {
VisitVector visits;
URLRow row =
MakeTypedUrlRow(url, title, typed_count, last_visit, hidden, &visits);
sync_pb::TypedUrlSpecifics typed_url_specifics;
WriteToTypedUrlSpecifics(row, visits, &typed_url_specifics);
- std::unique_ptr<MetadataChangeList> metadata_changes =
- bridge()->CreateMetadataChangeList();
+ std::string storage_key = GetStorageKey(typed_url_specifics.url());
+
EntityChangeList entity_changes;
switch (change_type) {
case EntityChange::ACTION_ADD:
@@ -320,15 +321,24 @@ class TypedURLSyncBridgeTest : public testing::Test {
std::string(), SpecificsToEntity(typed_url_specifics)));
break;
case EntityChange::ACTION_UPDATE:
- entity_changes.push_back(
- EntityChange::CreateUpdate(GetStorageKey(typed_url_specifics.url()),
- SpecificsToEntity(typed_url_specifics)));
+ entity_changes.push_back(EntityChange::CreateUpdate(
+ storage_key, SpecificsToEntity(typed_url_specifics)));
break;
case EntityChange::ACTION_DELETE:
- entity_changes.push_back(EntityChange::CreateDelete(
- GetStorageKey(typed_url_specifics.url())));
+ entity_changes.push_back(EntityChange::CreateDelete(storage_key));
break;
}
+
+ std::unique_ptr<MetadataChangeList> metadata_changes =
+ bridge()->CreateMetadataChangeList();
+ // There needs to be data present in the history DB before inserting
+ // metadata.
+ if (update_metadata) {
+ sync_pb::EntityMetadata metadata;
+ metadata.set_sequence_number(1);
+ metadata_changes->UpdateMetadata(storage_key, metadata);
+ }
+
bridge()->ApplySyncChanges(std::move(metadata_changes), entity_changes);
return visits;
}
@@ -416,7 +426,8 @@ class TypedURLSyncBridgeTest : public testing::Test {
}
static VisitRow CreateVisit(ui::PageTransition type, int64_t timestamp) {
- return VisitRow(0, base::Time::FromInternalValue(timestamp), 0, type, 0);
+ return VisitRow(0, base::Time::FromInternalValue(timestamp), 0, type, 0,
+ HistoryBackend::IsTypedIncrement(type));
}
static TypedURLSyncBridge::MergeResult MergeUrls(
@@ -998,6 +1009,65 @@ TEST_F(TypedURLSyncBridgeTest, DeleteLocalTypedUrl) {
ASSERT_TRUE(deleted_storage_keys.empty());
}
+// Expire several (but not all) local typed urls. This has only impact on local
+// store (metadata in the db and in-memory maps), nothing gets synced up.
+TEST_F(TypedURLSyncBridgeTest, ExpireLocalTypedUrl) {
+ StartSyncing(std::vector<TypedUrlSpecifics>());
+
+ URLRows url_rows;
+ std::vector<VisitVector> visit_vectors;
+ std::vector<std::string> urls;
+ urls.push_back("http://pie.com/");
+ urls.push_back("http://cake.com/");
+ urls.push_back("http://google.com/");
+ urls.push_back("http://foo.com/");
+ urls.push_back("http://bar.com/");
+
+ // Add the URLs into the history db and notify the bridge.
+ ASSERT_TRUE(BuildAndPushLocalChanges(5, 0, urls, &url_rows, &visit_vectors));
+ ASSERT_EQ(5U, processor().put_multimap().size());
+ int previous_put_size = processor().put_multimap().size();
+ // Store the typed_urls incl. metadata into the bridge's database.
+ for (const std::string& url : urls) {
+ ApplyUrlAndVisitsChange(url, kTitle, /*typed_count=*/1, /*last_visit=*/3,
+ /*hidden=*/false, /*update_metadata=*/true,
+ EntityChange::ACTION_ADD);
+ }
+
+ // Check all the metadata is here.
+ MetadataBatch metadata_batch;
+ metadata_store()->GetAllSyncMetadata(&metadata_batch);
+ ASSERT_EQ(5u, metadata_batch.TakeAllMetadata().size());
+
+ // Simulate expiration - delete some urls from the backend and create deleted
+ // row vector.
+ URLRows rows;
+ std::set<std::string> deleted_storage_keys;
+ for (size_t i = 0; i < 3u; ++i) {
+ std::string storage_key = GetStorageKey(url_rows[i].url().spec());
+ deleted_storage_keys.insert(storage_key);
+ fake_history_backend_->DeleteURL(url_rows[i].url());
+ rows.push_back(url_rows[i]);
+ }
+
+ // Notify typed url sync service of these URLs getting expired.
+ bridge()->OnURLsDeleted(fake_history_backend_.get(), /*all_history=*/false,
+ /*expired=*/true, rows, std::set<GURL>());
+
+ // This does not propagate to the processor.
+ EXPECT_EQ(0U, processor().put_multimap().size() - previous_put_size);
+ EXPECT_EQ(0U, processor().delete_set().size());
+
+ // The urls are removed from the metadata store.
+ MetadataBatch smaller_metadata_batch;
+ metadata_store()->GetAllSyncMetadata(&smaller_metadata_batch);
+ EXPECT_EQ(2u, smaller_metadata_batch.GetAllMetadata().size());
+ for (const auto& kv : smaller_metadata_batch.GetAllMetadata()) {
+ EXPECT_TRUE(deleted_storage_keys.find(kv.first) ==
+ deleted_storage_keys.end());
+ }
+}
+
// Saturate the visits for a typed url with both TYPED and LINK navigations.
// Check that no more than kMaxTypedURLVisits are synced, and that LINK visits
// are dropped rather than TYPED ones.
@@ -1105,8 +1175,10 @@ TEST_F(TypedURLSyncBridgeTest, ThrottleVisitLocalTypedUrl) {
// has started. Check that local DB is received the new URL and visit.
TEST_F(TypedURLSyncBridgeTest, AddUrlAndVisits) {
StartSyncing(std::vector<TypedUrlSpecifics>());
- VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
- EntityChange::ACTION_ADD);
+ VisitVector visits = ApplyUrlAndVisitsChange(
+ kURL, kTitle, /*typed_count=*/1, /*last_visit=*/3,
+ /*hidden=*/false,
+ /*update_metadata=*/false, EntityChange::ACTION_ADD);
ASSERT_EQ(0U, processor().put_multimap().size());
ASSERT_EQ(1U, processor().update_multimap().size());
@@ -1138,8 +1210,9 @@ TEST_F(TypedURLSyncBridgeTest, AddUrlAndVisits) {
// visit.
TEST_F(TypedURLSyncBridgeTest, AddExpiredUrlAndVisits) {
StartSyncing(std::vector<TypedUrlSpecifics>());
- VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, kExpiredVisit,
- false, EntityChange::ACTION_ADD);
+ VisitVector visits = ApplyUrlAndVisitsChange(
+ kURL, kTitle, /*typed_count=*/1, /*last_visit=*/kExpiredVisit,
+ /*hidden=*/false, /*update_metadata=*/false, EntityChange::ACTION_ADD);
ASSERT_EQ(0U, processor().put_multimap().size());
ASSERT_EQ(0U, processor().update_multimap().size());
@@ -1155,8 +1228,10 @@ TEST_F(TypedURLSyncBridgeTest, AddExpiredUrlAndVisits) {
TEST_F(TypedURLSyncBridgeTest, UpdateUrlAndVisits) {
StartSyncing(std::vector<TypedUrlSpecifics>());
- VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
- EntityChange::ACTION_ADD);
+ VisitVector visits = ApplyUrlAndVisitsChange(
+ kURL, kTitle, /*typed_count=*/1, /*last_visit=*/3,
+ /*hidden=*/false,
+ /*update_metadata=*/false, EntityChange::ACTION_ADD);
base::Time visit_time = base::Time::FromInternalValue(3);
VisitVector all_visits;
URLRow url_row;
@@ -1173,8 +1248,10 @@ TEST_F(TypedURLSyncBridgeTest, UpdateUrlAndVisits) {
EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
- VisitVector new_visits = ApplyUrlAndVisitsChange(kURL, kTitle2, 2, 6, false,
- EntityChange::ACTION_UPDATE);
+ VisitVector new_visits = ApplyUrlAndVisitsChange(
+ kURL, kTitle2, /*typed_count=*/2, /*last_visit=*/6,
+ /*hidden=*/false,
+ /*update_metadata=*/false, EntityChange::ACTION_UPDATE);
base::Time new_visit_time = base::Time::FromInternalValue(6);
url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
@@ -1219,7 +1296,8 @@ TEST_F(TypedURLSyncBridgeTest, DeleteUrlAndVisits) {
// changes back from fake_history_backend_.
AddObserver();
- ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
+ ApplyUrlAndVisitsChange(kURL, kTitle, /*typed_count=*/1, /*last_visit=*/3,
+ /*hidden=*/false, /*update_metadata=*/false,
EntityChange::ACTION_DELETE);
EXPECT_FALSE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
@@ -1241,7 +1319,7 @@ TEST_F(TypedURLSyncBridgeTest, DiffVisitsSame) {
for (int64_t visit : visits) {
old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
- ui::PAGE_TRANSITION_TYPED, 0));
+ ui::PAGE_TRANSITION_TYPED, 0, true));
new_url.add_visits(visit);
new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
}
@@ -1271,7 +1349,7 @@ TEST_F(TypedURLSyncBridgeTest, DiffVisitsRemove) {
for (int64_t visit : visits_left) {
old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
- ui::PAGE_TRANSITION_TYPED, 0));
+ ui::PAGE_TRANSITION_TYPED, 0, true));
}
for (int64_t visit : visits_right) {
@@ -1305,7 +1383,7 @@ TEST_F(TypedURLSyncBridgeTest, DiffVisitsAdd) {
for (int64_t visit : visits_left) {
old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
- ui::PAGE_TRANSITION_TYPED, 0));
+ ui::PAGE_TRANSITION_TYPED, 0, true));
}
for (int64_t visit : visits_right) {
@@ -1495,7 +1573,7 @@ TEST_F(TypedURLSyncBridgeTest, MergeUrlsAfterExpiration) {
// First, create a history row that has two visits, with timestamps 2 and 3.
VisitVector(history_visits);
history_visits.push_back(VisitRow(0, base::Time::FromInternalValue(2), 0,
- ui::PAGE_TRANSITION_TYPED, 0));
+ ui::PAGE_TRANSITION_TYPED, 0, true));
URLRow history_url(
MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &history_visits));
diff --git a/chromium/components/history/core/browser/visit_database.cc b/chromium/components/history/core/browser/visit_database.cc
index 0ef84afb008..8dca02c1f2b 100644
--- a/chromium/components/history/core/browser/visit_database.cc
+++ b/chromium/components/history/core/browser/visit_database.cc
@@ -17,8 +17,11 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
+#include "components/google/core/browser/google_util.h"
+#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/url_database.h"
#include "sql/statement.h"
+#include "sql/transaction.h"
#include "ui/base/page_transition_types.h"
#include "url/url_constants.h"
@@ -42,7 +45,8 @@ bool VisitDatabase::InitVisitTable() {
"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)"))
+ "visit_duration INTEGER DEFAULT 0 NOT NULL,"
+ "incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL)"))
return false;
}
@@ -98,6 +102,7 @@ void VisitDatabase::FillVisitRow(const sql::Statement& statement,
visit->segment_id = statement.ColumnInt64(5);
visit->visit_duration =
base::TimeDelta::FromInternalValue(statement.ColumnInt64(6));
+ visit->incremented_omnibox_typed_score = statement.ColumnBool(7);
}
// static
@@ -149,16 +154,19 @@ bool VisitDatabase::FillVisitVectorWithOptions(sql::Statement& statement,
}
VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) {
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
"INSERT INTO visits "
"(url, visit_time, from_visit, transition, segment_id, "
- "visit_duration) VALUES (?,?,?,?,?,?)"));
+ "visit_duration, incremented_omnibox_typed_score) "
+ "VALUES (?,?,?,?,?,?,?)"));
statement.BindInt64(0, visit->url_id);
statement.BindInt64(1, visit->visit_time.ToInternalValue());
statement.BindInt64(2, visit->referring_visit);
statement.BindInt64(3, visit->transition);
statement.BindInt64(4, visit->segment_id);
statement.BindInt64(5, visit->visit_duration.ToInternalValue());
+ statement.BindBool(6, visit->incremented_omnibox_typed_score);
if (!statement.Run()) {
DVLOG(0) << "Failed to execute visit insert statement: "
@@ -235,17 +243,19 @@ bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) {
if (visit.visit_id == visit.referring_visit)
return false;
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
"UPDATE visits SET "
"url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,"
- "visit_duration=? WHERE id=?"));
+ "visit_duration=?,incremented_omnibox_typed_score=? WHERE id=?"));
statement.BindInt64(0, visit.url_id);
statement.BindInt64(1, visit.visit_time.ToInternalValue());
statement.BindInt64(2, visit.referring_visit);
statement.BindInt64(3, visit.transition);
statement.BindInt64(4, visit.segment_id);
statement.BindInt64(5, visit.visit_duration.ToInternalValue());
- statement.BindInt64(6, visit.visit_id);
+ statement.BindBool(6, visit.incremented_omnibox_typed_score);
+ statement.BindInt64(7, visit.visit_id);
return statement.Run();
}
@@ -610,6 +620,46 @@ void VisitDatabase::GetVisitsSource(const VisitVector& visits,
}
}
+std::vector<DomainVisit>
+VisitDatabase::GetGoogleDomainVisitsFromSearchesInRange(base::Time begin_time,
+ base::Time end_time) {
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "SELECT "
+ " visit_time, "
+ " u.url "
+ "FROM "
+ " urls u JOIN visits v ON u.id = v.url "
+ "WHERE "
+ // Pre-filtering to limit the number of entries to process in
+ // C++. The url column is indexed so this makes the query more
+ // efficient. We then confirm in C++ that the domain of an entry
+ // is a valid Google domain before counting the visit.
+ " (u.url LIKE \"https://www.google.__/search%\" OR "
+ " u.url LIKE \"https://www.google.___/search%\" OR "
+ " u.url LIKE \"https://www.google.__.__/search%\" OR "
+ " u.url LIKE \"https://www.google.___.__/search%\") AND "
+ // Restrict to visits that are more recent than the specified start
+ // time.
+ " visit_time >= ? AND "
+ // Restrict to visits that are older than the specified end time.
+ " visit_time < ? "));
+ statement.BindInt64(0,
+ begin_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ statement.BindInt64(1, end_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ std::vector<DomainVisit> domain_visits;
+ while (statement.Step()) {
+ const GURL url(statement.ColumnString(1));
+ if (google_util::IsGoogleSearchUrl(url)) {
+ domain_visits.emplace_back(
+ url.host(),
+ base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(0))));
+ }
+ }
+ return domain_visits;
+}
+
bool VisitDatabase::MigrateVisitsWithoutDuration() {
if (!GetDB().DoesTableExist("visits")) {
NOTREACHED() << " Visits table should exist before migration";
@@ -626,4 +676,48 @@ bool VisitDatabase::MigrateVisitsWithoutDuration() {
return true;
}
+bool VisitDatabase::MigrateVisitsWithoutIncrementedOmniboxTypedScore() {
+ if (!GetDB().DoesTableExist("visits")) {
+ NOTREACHED() << " Visits table should exist before migration";
+ return false;
+ }
+
+ if (!GetDB().DoesColumnExist("visits", "incremented_omnibox_typed_score")) {
+ // Wrap the creation and initialization of the new column in a transaction
+ // since the value must be computed outside of SQL and iteratively updated.
+ sql::Transaction committer(&GetDB());
+ if (!committer.Begin())
+ return false;
+
+ // Old versions don't have the incremented_omnibox_typed_score column, we
+ // modify the table to add that field. We iterate through the table and
+ // compute the result for each row.
+ if (!GetDB().Execute("ALTER TABLE visits "
+ "ADD COLUMN incremented_omnibox_typed_score BOOLEAN "
+ "DEFAULT FALSE NOT NULL"))
+ return false;
+
+ // Iterate through rows in the visits table and update each with the
+ // appropriate increment_omnibox_typed_score value. Because this column was
+ // newly added, the existing (default) value is not valid/correct.
+ sql::Statement read(GetDB().GetUniqueStatement(
+ "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits"));
+ while (read.is_valid() && read.Step()) {
+ VisitRow row;
+ FillVisitRow(read, &row);
+ // Check if the visit row is in an invalid state and if it is then
+ // leave the new field as the default value.
+ if (row.visit_id == row.referring_visit)
+ continue;
+ row.incremented_omnibox_typed_score =
+ HistoryBackend::IsTypedIncrement(row.transition);
+ if (!UpdateVisitRow(row))
+ return false;
+ }
+ if (!read.Succeeded() || !committer.Commit())
+ return false;
+ }
+ return true;
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/visit_database.h b/chromium/components/history/core/browser/visit_database.h
index ee950544f97..c4ec7ace7b1 100644
--- a/chromium/components/history/core/browser/visit_database.h
+++ b/chromium/components/history/core/browser/visit_database.h
@@ -188,6 +188,13 @@ class VisitDatabase {
void GetVisitsSource(const VisitVector& visits,
VisitSourceMap* sources);
+ // Returns the list of Google domain visits of the user based on the Google
+ // searches issued in the specified time interval.
+ // begin_time is inclusive, end_time is exclusive.
+ std::vector<DomainVisit> GetGoogleDomainVisitsFromSearchesInRange(
+ base::Time begin_time,
+ base::Time end_time);
+
protected:
// Returns the database for the functions in this interface.
virtual sql::Connection& GetDB() = 0;
@@ -216,14 +223,19 @@ class VisitDatabase {
// don't have visit_duration column yet.
bool MigrateVisitsWithoutDuration();
+ // Called by the derived classes to migrate the older visits table which
+ // don't have incremented_omnibox_typed_score column yet.
+ bool MigrateVisitsWithoutIncrementedOmniboxTypedScore();
+
private:
DISALLOW_COPY_AND_ASSIGN(VisitDatabase);
};
-// Rows, in order, of the visit table.
-#define HISTORY_VISIT_ROW_FIELDS \
- " id,url,visit_time,from_visit,transition,segment_id,visit_duration "
+// Columns, in order, of the visit table.
+#define HISTORY_VISIT_ROW_FIELDS \
+ " id,url,visit_time,from_visit,transition,segment_id,visit_duration," \
+ "incremented_omnibox_typed_score "
} // namespace history
diff --git a/chromium/components/history/core/browser/visit_database_unittest.cc b/chromium/components/history/core/browser/visit_database_unittest.cc
index 77be2f6388d..ee7aad30b4e 100644
--- a/chromium/components/history/core/browser/visit_database_unittest.cc
+++ b/chromium/components/history/core/browser/visit_database_unittest.cc
@@ -14,11 +14,16 @@
#include "components/history/core/browser/url_database.h"
#include "components/history/core/browser/visit_database.h"
#include "sql/connection.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
using base::Time;
using base::TimeDelta;
+using testing::AllOf;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::Property;
namespace history {
@@ -71,19 +76,18 @@ class VisitDatabaseTest : public PlatformTest,
TEST_F(VisitDatabaseTest, Add) {
// Add one visit.
- VisitRow visit_info1(1, Time::Now(), 0, ui::PAGE_TRANSITION_LINK, 0);
+ VisitRow visit_info1(1, Time::Now(), 0, ui::PAGE_TRANSITION_LINK, 0, false);
EXPECT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
// Add second visit for the same page.
VisitRow visit_info2(visit_info1.url_id,
- visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
- ui::PAGE_TRANSITION_TYPED, 0);
+ visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
+ ui::PAGE_TRANSITION_TYPED, 0, true);
EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED));
// Add third visit for a different page.
- VisitRow visit_info3(2,
- visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
- ui::PAGE_TRANSITION_LINK, 0);
+ VisitRow visit_info3(2, visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
+ ui::PAGE_TRANSITION_LINK, 0, false);
EXPECT_TRUE(AddVisit(&visit_info3, SOURCE_BROWSED));
// Query the first two.
@@ -102,17 +106,17 @@ TEST_F(VisitDatabaseTest, Delete) {
// should link them.
static const int kTime1 = 1000;
VisitRow visit_info1(1, Time::FromInternalValue(kTime1), 0,
- ui::PAGE_TRANSITION_LINK, 0);
+ ui::PAGE_TRANSITION_LINK, 0, false);
EXPECT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
static const int kTime2 = kTime1 + 1;
- VisitRow visit_info2(1, Time::FromInternalValue(kTime2),
- visit_info1.visit_id, ui::PAGE_TRANSITION_LINK, 0);
+ VisitRow visit_info2(1, Time::FromInternalValue(kTime2), visit_info1.visit_id,
+ ui::PAGE_TRANSITION_LINK, 0, false);
EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED));
static const int kTime3 = kTime2 + 1;
- VisitRow visit_info3(1, Time::FromInternalValue(kTime3),
- visit_info2.visit_id, ui::PAGE_TRANSITION_LINK, 0);
+ VisitRow visit_info3(1, Time::FromInternalValue(kTime3), visit_info2.visit_id,
+ ui::PAGE_TRANSITION_LINK, 0, false);
EXPECT_TRUE(AddVisit(&visit_info3, SOURCE_BROWSED));
// First make sure all the visits are there.
@@ -138,7 +142,8 @@ TEST_F(VisitDatabaseTest, Delete) {
TEST_F(VisitDatabaseTest, Update) {
// Make something in the database.
- VisitRow original(1, Time::Now(), 23, ui::PageTransitionFromInt(0), 19);
+ VisitRow original(1, Time::Now(), 23, ui::PageTransitionFromInt(0), 19,
+ false);
AddVisit(&original, SOURCE_BROWSED);
// Mutate that row.
@@ -165,61 +170,58 @@ std::vector<VisitRow> GetTestVisitRows() {
base::Time base_time = Time::UnixEpoch().LocalMidnight();
// Add one visit.
- VisitRow visit_info1(1, base_time + TimeDelta::FromMinutes(1), 0,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_LINK |
- ui::PAGE_TRANSITION_CHAIN_START |
- ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ VisitRow visit_info1(
+ 1, base_time + TimeDelta::FromMinutes(1), 0,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CHAIN_START |
+ ui::PAGE_TRANSITION_CHAIN_END),
+ 0, false);
visit_info1.visit_id = 1;
// Add second visit for the same page.
- VisitRow visit_info2(visit_info1.url_id,
- visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_TYPED |
- ui::PAGE_TRANSITION_CHAIN_START |
- ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ VisitRow visit_info2(
+ visit_info1.url_id, visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_CHAIN_START |
+ ui::PAGE_TRANSITION_CHAIN_END),
+ 0, true);
visit_info2.visit_id = 2;
// Add third visit for a different page.
- VisitRow visit_info3(2,
- visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_LINK |
- ui::PAGE_TRANSITION_CHAIN_START),
- 0);
+ VisitRow visit_info3(
+ 2, visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CHAIN_START),
+ 0, false);
visit_info3.visit_id = 3;
// Add a redirect visit from the last page.
- VisitRow visit_info4(3,
- visit_info1.visit_time + TimeDelta::FromSeconds(3), visit_info3.visit_id,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_SERVER_REDIRECT |
- ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ VisitRow visit_info4(
+ 3, visit_info1.visit_time + TimeDelta::FromSeconds(3),
+ visit_info3.visit_id,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_SERVER_REDIRECT |
+ ui::PAGE_TRANSITION_CHAIN_END),
+ 0, false);
visit_info4.visit_id = 4;
// Add a subframe visit.
- VisitRow visit_info5(4,
- visit_info1.visit_time + TimeDelta::FromSeconds(4), visit_info4.visit_id,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_AUTO_SUBFRAME |
- ui::PAGE_TRANSITION_CHAIN_START |
- ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ VisitRow visit_info5(
+ 4, visit_info1.visit_time + TimeDelta::FromSeconds(4),
+ visit_info4.visit_id,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME |
+ ui::PAGE_TRANSITION_CHAIN_START |
+ ui::PAGE_TRANSITION_CHAIN_END),
+ 0, false);
visit_info5.visit_id = 5;
// Add third visit for the same URL as visit 1 and 2, but exactly a day
// later than visit 2.
- VisitRow visit_info6(visit_info1.url_id,
- visit_info2.visit_time + TimeDelta::FromDays(1), 1,
- ui::PageTransitionFromInt(
- ui::PAGE_TRANSITION_TYPED |
- ui::PAGE_TRANSITION_CHAIN_START |
- ui::PAGE_TRANSITION_CHAIN_END),
- 0);
+ VisitRow visit_info6(
+ visit_info1.url_id, visit_info2.visit_time + TimeDelta::FromDays(1), 1,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_CHAIN_START |
+ ui::PAGE_TRANSITION_CHAIN_END),
+ 0, true);
visit_info6.visit_id = 6;
std::vector<VisitRow> test_visit_rows;
@@ -367,13 +369,13 @@ TEST_F(VisitDatabaseTest, GetAllURLIDsForTransition) {
TEST_F(VisitDatabaseTest, VisitSource) {
// Add visits.
- VisitRow visit_info1(111, Time::Now(), 0, ui::PAGE_TRANSITION_LINK, 0);
+ VisitRow visit_info1(111, Time::Now(), 0, ui::PAGE_TRANSITION_LINK, 0, false);
ASSERT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
- VisitRow visit_info2(112, Time::Now(), 1, ui::PAGE_TRANSITION_TYPED, 0);
+ VisitRow visit_info2(112, Time::Now(), 1, ui::PAGE_TRANSITION_TYPED, 0, true);
ASSERT_TRUE(AddVisit(&visit_info2, SOURCE_SYNCED));
- VisitRow visit_info3(113, Time::Now(), 0, ui::PAGE_TRANSITION_TYPED, 0);
+ VisitRow visit_info3(113, Time::Now(), 0, ui::PAGE_TRANSITION_TYPED, 0, true);
ASSERT_TRUE(AddVisit(&visit_info3, SOURCE_EXTENSION));
// Query each visit.
@@ -447,27 +449,27 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
// Add 5 visits (3 distinct URLs) for the day before yesterday.
// Whether the URL was browsed on this machine or synced has no effect.
- VisitRow first_day_1(1, now, 0, standard_transition, 0);
+ VisitRow first_day_1(1, now, 0, standard_transition, 0, true);
first_day_1.visit_id = 1;
AddVisit(&first_day_1, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
- VisitRow first_day_2(2, now, 0, standard_transition, 0);
+ VisitRow first_day_2(2, now, 0, standard_transition, 0, true);
first_day_2.visit_id = 2;
AddVisit(&first_day_2, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
- VisitRow first_day_3(1, now, 0, standard_transition, 0);
+ VisitRow first_day_3(1, now, 0, standard_transition, 0, true);
first_day_3.visit_id = 3;
AddVisit(&first_day_3, SOURCE_SYNCED);
now += TimeDelta::FromHours(1);
- VisitRow first_day_4(3, now, 0, standard_transition, 0);
+ VisitRow first_day_4(3, now, 0, standard_transition, 0, true);
first_day_4.visit_id = 4;
AddVisit(&first_day_4, SOURCE_SYNCED);
now += TimeDelta::FromHours(1);
- VisitRow first_day_5(2, now, 0, standard_transition, 0);
+ VisitRow first_day_5(2, now, 0, standard_transition, 0, true);
first_day_5.visit_id = 5;
AddVisit(&first_day_5, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
@@ -476,22 +478,22 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
// a user-visible navigation. Of the remaining 3, only 2 are unique.
now = yesterday;
- VisitRow second_day_1(1, now, 0, standard_transition, 0);
+ VisitRow second_day_1(1, now, 0, standard_transition, 0, true);
second_day_1.visit_id = 6;
AddVisit(&second_day_1, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
- VisitRow second_day_2(1, now, 0, standard_transition, 0);
+ VisitRow second_day_2(1, now, 0, standard_transition, 0, true);
second_day_2.visit_id = 7;
AddVisit(&second_day_2, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
- VisitRow second_day_3(2, now, 0, ui::PAGE_TRANSITION_AUTO_SUBFRAME, 0);
+ VisitRow second_day_3(2, now, 0, ui::PAGE_TRANSITION_AUTO_SUBFRAME, 0, false);
second_day_3.visit_id = 8;
AddVisit(&second_day_3, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
- VisitRow second_day_4(3, now, 0, standard_transition, 0);
+ VisitRow second_day_4(3, now, 0, standard_transition, 0, true);
second_day_4.visit_id = 9;
AddVisit(&second_day_4, SOURCE_BROWSED);
now += TimeDelta::FromHours(1);
@@ -568,12 +570,12 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
// 24 hours later. The count should be 1, not 2, because the day is longer
// than 24 hours, and the two visits will be regarded as duplicate.
if (!shift_backward.is_null()) {
- VisitRow backward_1(1, shift_backward, 0, standard_transition, 0);
+ VisitRow backward_1(1, shift_backward, 0, standard_transition, 0, true);
backward_1.visit_id = 10;
AddVisit(&backward_1, SOURCE_BROWSED);
- VisitRow backward_2(1, shift_backward + TimeDelta::FromHours(24),
- 0, standard_transition, 0);
+ VisitRow backward_2(1, shift_backward + TimeDelta::FromHours(24), 0,
+ standard_transition, 0, true);
backward_2.visit_id = 11;
AddVisit(&backward_2, SOURCE_BROWSED);
@@ -588,14 +590,15 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
// regarded as duplicate in a normal 24 hour day, but in this case the second
// visit is already in the next day.
if (!shift_forward.is_null()) {
- VisitRow forward_1(1, shift_forward, 0, standard_transition, 0);
+ VisitRow forward_1(1, shift_forward, 0, standard_transition, 0, true);
forward_1.visit_id = 12;
AddVisit(&forward_1, SOURCE_BROWSED);
Time almost_24_hours_later = shift_forward +
TimeDelta::FromHours(24) -
TimeDelta::FromMicroseconds(1);
- VisitRow forward_2(1, almost_24_hours_later, 0, standard_transition, 0);
+ VisitRow forward_2(1, almost_24_hours_later, 0, standard_transition, 0,
+ true);
forward_2.visit_id = 13;
AddVisit(&forward_2, SOURCE_BROWSED);
@@ -606,4 +609,89 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
}
}
+TEST_F(VisitDatabaseTest, GetGoogleDomainVisitsFromSearchesInRange_NoVisits) {
+ const auto begin_time = base::Time::Now();
+ EXPECT_THAT(GetGoogleDomainVisitsFromSearchesInRange(
+ begin_time, begin_time + base::TimeDelta::FromDays(1)),
+ IsEmpty());
+}
+
+TEST_F(VisitDatabaseTest,
+ GetGoogleDomainVisitsFromSearchesInRange_TwoVistsInRange) {
+ const auto begin_time = base::Time::Now();
+ // Out of range, one hour before begin time.
+ VisitRow row{AddURL(URLRow(GURL("https://www.google.fr/search?q=foo"))),
+ begin_time + base::TimeDelta::FromHours(-1),
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+ // In range, exactly begin time.
+ row = {AddURL(URLRow(GURL("https://www.google.com/search?q=foo"))),
+ begin_time,
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+ // In range, 23 hours after begin time.
+ row = {AddURL(URLRow(GURL("https://www.google.ch/search?q=foo"))),
+ begin_time + base::TimeDelta::FromHours(23),
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+ // Out of range, exactly a day after begin time.
+ row = {AddURL(URLRow(GURL("https://www.google.de/search?q=foo"))),
+ begin_time + base::TimeDelta::FromHours(24),
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+
+ EXPECT_THAT(
+ GetGoogleDomainVisitsFromSearchesInRange(
+ begin_time, begin_time + base::TimeDelta::FromDays(1)),
+ ElementsAre(
+ AllOf(Property(&DomainVisit::domain, "www.google.com"),
+ Property(&DomainVisit::visit_time, begin_time)),
+ AllOf(Property(&DomainVisit::domain, "www.google.ch"),
+ Property(&DomainVisit::visit_time,
+ begin_time + base::TimeDelta::FromHours(23)))));
+}
+
+TEST_F(VisitDatabaseTest, GetGoogleDomainVisitsFromSearchesInRange_NotSearch) {
+ const auto begin_time = base::Time::Now();
+ VisitRow row{AddURL(URLRow(GURL("https://www.google.fr/searchin"))),
+ begin_time,
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+
+ EXPECT_THAT(GetGoogleDomainVisitsFromSearchesInRange(
+ begin_time, begin_time + base::TimeDelta::FromDays(1)),
+ IsEmpty());
+}
+
+TEST_F(VisitDatabaseTest,
+ GetGoogleDomainVisitsFromSearchesInRange_InvalidGoogleDomain) {
+ const auto begin_time = base::Time::Now();
+ VisitRow row{AddURL(URLRow(GURL("https://www.google.foo/search?q=foo"))),
+ begin_time,
+ 0,
+ ui::PageTransitionFromInt(0),
+ 0,
+ false};
+ AddVisit(&row, SOURCE_BROWSED);
+
+ EXPECT_THAT(GetGoogleDomainVisitsFromSearchesInRange(
+ begin_time, begin_time + base::TimeDelta::FromDays(1)),
+ IsEmpty());
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/web_history_service.cc b/chromium/components/history/core/browser/web_history_service.cc
index 6a6ae16bbd1..325566e56eb 100644
--- a/chromium/components/history/core/browser/web_history_service.cc
+++ b/chromium/components/history/core/browser/web_history_service.cc
@@ -379,7 +379,7 @@ std::unique_ptr<base::DictionaryValue> WebHistoryService::ReadResponse(
if (request->GetResponseCode() == net::HTTP_OK) {
std::unique_ptr<base::Value> value =
base::JSONReader::Read(request->GetResponseBody());
- if (value.get() && value.get()->is_dict())
+ if (value && value->is_dict())
result.reset(static_cast<base::DictionaryValue*>(value.release()));
else
DLOG(WARNING) << "Non-JSON response received from history server.";