summaryrefslogtreecommitdiff
path: root/chromium/components/ntp_tiles
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/components/ntp_tiles
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
downloadqtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/ntp_tiles')
-rw-r--r--chromium/components/ntp_tiles/BUILD.gn19
-rw-r--r--chromium/components/ntp_tiles/DEPS3
-rw-r--r--chromium/components/ntp_tiles/OWNERS1
-rw-r--r--chromium/components/ntp_tiles/constants.cc19
-rw-r--r--chromium/components/ntp_tiles/constants.h27
-rw-r--r--chromium/components/ntp_tiles/custom_links_manager_impl.cc9
-rw-r--r--chromium/components/ntp_tiles/features.cc11
-rw-r--r--chromium/components/ntp_tiles/features.h15
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl.cc5
-rw-r--r--chromium/components/ntp_tiles/json_unsafe_parser.cc41
-rw-r--r--chromium/components/ntp_tiles/json_unsafe_parser.h40
-rw-r--r--chromium/components/ntp_tiles/metrics.cc7
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.cc76
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.h32
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites_unittest.cc250
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl.cc36
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl.h10
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl_unittest.cc53
-rw-r--r--chromium/components/ntp_tiles/tile_source.h2
-rw-r--r--chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc5
20 files changed, 360 insertions, 301 deletions
diff --git a/chromium/components/ntp_tiles/BUILD.gn b/chromium/components/ntp_tiles/BUILD.gn
index 33d2c608dba..244ad33d493 100644
--- a/chromium/components/ntp_tiles/BUILD.gn
+++ b/chromium/components/ntp_tiles/BUILD.gn
@@ -53,7 +53,6 @@ static_library("ntp_tiles") {
"//components/suggestions",
]
deps = [
- "//components/data_use_measurement/core",
"//components/favicon/core",
"//components/favicon_base",
"//components/google/core/browser",
@@ -72,22 +71,6 @@ static_library("ntp_tiles") {
]
}
-# If you want to use this, let us (ntp-dev@chromium.org) know. In that case, it
-# should be moved to a more common location as it has 2+ callers already.
-# Note that you probably shouldn't be using it outside of ios or tests.
-source_set("json_unsafe_parser") {
- testonly = !is_ios
-
- sources = [
- "json_unsafe_parser.cc",
- "json_unsafe_parser.h",
- ]
-
- public_deps = [
- "//base",
- ]
-}
-
source_set("unit_tests") {
testonly = true
sources = [
@@ -100,7 +83,6 @@ source_set("unit_tests") {
]
deps = [
- ":json_unsafe_parser",
":ntp_tiles",
"//base/test:test_support",
"//components/favicon/core",
@@ -112,6 +94,7 @@ source_set("unit_tests") {
"//components/rappor:test_support",
"//components/sync_preferences:test_support",
"//net:test_support",
+ "//services/data_decoder/public/cpp:test_support",
"//services/network:test_support",
"//services/network/public/cpp",
"//testing/gmock",
diff --git a/chromium/components/ntp_tiles/DEPS b/chromium/components/ntp_tiles/DEPS
index 18f2f118b9b..985869d766a 100644
--- a/chromium/components/ntp_tiles/DEPS
+++ b/chromium/components/ntp_tiles/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+components/data_use_measurement/core",
"+components/favicon",
"+components/favicon_base",
"+components/google/core",
@@ -18,9 +17,9 @@ include_rules = [
"+components/variations",
"+jni",
"+net",
+ "+services/data_decoder/public/cpp/testing_json_parser.h",
"+services/network/public/cpp",
"+services/network/test",
"+ui/gfx",
"+ui/base",
]
-
diff --git a/chromium/components/ntp_tiles/OWNERS b/chromium/components/ntp_tiles/OWNERS
index e5dfa00fed9..91a328f7120 100644
--- a/chromium/components/ntp_tiles/OWNERS
+++ b/chromium/components/ntp_tiles/OWNERS
@@ -1,4 +1,5 @@
fhorschig@chromium.org
jkrcal@chromium.org
+kristipark@chromium.org
mastiz@chromium.org
treib@chromium.org
diff --git a/chromium/components/ntp_tiles/constants.cc b/chromium/components/ntp_tiles/constants.cc
index b40488bcd09..ed849b2bf3c 100644
--- a/chromium/components/ntp_tiles/constants.cc
+++ b/chromium/components/ntp_tiles/constants.cc
@@ -4,23 +4,12 @@
#include "components/ntp_tiles/constants.h"
-#include "base/feature_list.h"
-#include "ui/base/ui_base_features.h"
-
namespace ntp_tiles {
-const char kPopularSitesFieldTrialName[] = "NTPPopularSites";
-
-const base::Feature kPopularSitesBakedInContentFeature{
- "NTPPopularSitesBakedInContent", base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kNtpMostLikelyFaviconsFromServerFeature{
- "NTPMostLikelyFaviconsFromServer", base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kSiteExplorationUiFeature{
- "SiteExplorationUi", base::FEATURE_DISABLED_BY_DEFAULT};
+const size_t kMaxNumCustomLinks = 10;
-const base::Feature kUsePopularSitesSuggestions{
- "UsePopularSitesSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
+// Because the custom links feature has an additional "Add shortcut" button, 9
+// tiles are required to balance the Most Visited rows on the NTP.
+const int kMaxNumMostVisited = 9;
} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/constants.h b/chromium/components/ntp_tiles/constants.h
index 7395995f975..eb7a95f0b1a 100644
--- a/chromium/components/ntp_tiles/constants.h
+++ b/chromium/components/ntp_tiles/constants.h
@@ -5,29 +5,20 @@
#ifndef COMPONENTS_NTP_TILES_CONSTANTS_H_
#define COMPONENTS_NTP_TILES_CONSTANTS_H_
-namespace base {
-struct Feature;
-} // namespace base
+#include <stddef.h>
-namespace ntp_tiles {
-
-// Name of the field trial to configure PopularSites.
-extern const char kPopularSitesFieldTrialName[];
+#include <utility>
-// This feature is enabled by default. Otherwise, users who need it would not
-// get the right configuration timely enough. The configuration affects only
-// Android or iOS users.
-extern const base::Feature kPopularSitesBakedInContentFeature;
+namespace ntp_tiles {
-// Feature to allow the new Google favicon server for fetching favicons for Most
-// Likely tiles on the New Tab Page.
-extern const base::Feature kNtpMostLikelyFaviconsFromServerFeature;
+// Maximum number of custom links that can be set by the user. Used on desktop.
+extern const size_t kMaxNumCustomLinks;
-// Feature to provide site exploration tiles in addition to personal tiles.
-extern const base::Feature kSiteExplorationUiFeature;
+// Maximum number of Most Visited sites that will be generated. Used on desktop.
+extern const int kMaxNumMostVisited;
-// If this feature is enabled, we enable popular sites in the suggestions UI.
-extern const base::Feature kUsePopularSitesSuggestions;
+// Maximum number of tiles that can be shown on the NTP.
+const int kMaxNumTiles = 10;
} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/custom_links_manager_impl.cc b/chromium/components/ntp_tiles/custom_links_manager_impl.cc
index 75bca9b0393..32b562a39d1 100644
--- a/chromium/components/ntp_tiles/custom_links_manager_impl.cc
+++ b/chromium/components/ntp_tiles/custom_links_manager_impl.cc
@@ -10,18 +10,13 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "components/ntp_tiles/constants.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
namespace ntp_tiles {
-namespace {
-
-const int kMaxNumLinks = 10;
-
-} // namespace
-
CustomLinksManagerImpl::CustomLinksManagerImpl(
PrefService* prefs,
history::HistoryService* history_service)
@@ -80,7 +75,7 @@ const std::vector<CustomLinksManager::Link>& CustomLinksManagerImpl::GetLinks()
bool CustomLinksManagerImpl::AddLink(const GURL& url,
const base::string16& title) {
if (!IsInitialized() || !url.is_valid() ||
- current_links_.size() == kMaxNumLinks) {
+ current_links_.size() == ntp_tiles::kMaxNumCustomLinks) {
return false;
}
diff --git a/chromium/components/ntp_tiles/features.cc b/chromium/components/ntp_tiles/features.cc
index d1f3c33814c..0ea51f0746e 100644
--- a/chromium/components/ntp_tiles/features.cc
+++ b/chromium/components/ntp_tiles/features.cc
@@ -9,6 +9,17 @@
namespace ntp_tiles {
+const char kPopularSitesFieldTrialName[] = "NTPPopularSites";
+
+const base::Feature kPopularSitesBakedInContentFeature{
+ "NTPPopularSitesBakedInContent", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kNtpMostLikelyFaviconsFromServerFeature{
+ "NTPMostLikelyFaviconsFromServer", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kUsePopularSitesSuggestions{
+ "UsePopularSitesSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
+
const base::Feature kDefaultSearchShortcut{"DefaultSearchShortcut",
base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/components/ntp_tiles/features.h b/chromium/components/ntp_tiles/features.h
index 0c60cfc0d7b..39dc61dcdb2 100644
--- a/chromium/components/ntp_tiles/features.h
+++ b/chromium/components/ntp_tiles/features.h
@@ -11,6 +11,21 @@ struct Feature;
namespace ntp_tiles {
+// Name of the field trial to configure PopularSites.
+extern const char kPopularSitesFieldTrialName[];
+
+// This feature is enabled by default. Otherwise, users who need it would not
+// get the right configuration timely enough. The configuration affects only
+// Android or iOS users.
+extern const base::Feature kPopularSitesBakedInContentFeature;
+
+// Feature to allow the new Google favicon server for fetching favicons for Most
+// Likely tiles on the New Tab Page.
+extern const base::Feature kNtpMostLikelyFaviconsFromServerFeature;
+
+// If this feature is enabled, we enable popular sites in the suggestions UI.
+extern const base::Feature kUsePopularSitesSuggestions;
+
// If enabled, show a Google search shortcut on the NTP by default.
extern const base::Feature kDefaultSearchShortcut;
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl.cc b/chromium/components/ntp_tiles/icon_cacher_impl.cc
index a4a62030462..aadc7ddc205 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl.cc
+++ b/chromium/components/ntp_tiles/icon_cacher_impl.cc
@@ -18,7 +18,7 @@
#include "components/favicon_base/favicon_util.h"
#include "components/image_fetcher/core/image_decoder.h"
#include "components/image_fetcher/core/image_fetcher.h"
-#include "components/ntp_tiles/constants.h"
+#include "components/ntp_tiles/features.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/geometry/size.h"
@@ -270,7 +270,8 @@ void IconCacherImpl::OnGetLargeIconOrFallbackStyleFinished(
page_url,
GetMinimumFetchingSizeForChromeSuggestionsFaviconsFromServer(),
GetDesiredFetchingSizeForChromeSuggestionsFaviconsFromServer()),
- /*may_page_url_be_private=*/true, traffic_annotation,
+ /*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
+ traffic_annotation,
base::Bind(&IconCacherImpl::OnMostLikelyFaviconDownloaded,
weak_ptr_factory_.GetWeakPtr(), page_url));
}
diff --git a/chromium/components/ntp_tiles/json_unsafe_parser.cc b/chromium/components/ntp_tiles/json_unsafe_parser.cc
deleted file mode 100644
index e1281f00050..00000000000
--- a/chromium/components/ntp_tiles/json_unsafe_parser.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 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/ntp_tiles/json_unsafe_parser.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/json/json_parser.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/values.h"
-
-namespace ntp_tiles {
-
-void JsonUnsafeParser::Parse(const std::string& unsafe_json,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(
- [](const std::string& unsafe_json,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) {
- std::string error_msg;
- int error_line, error_column;
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadAndReturnErrorDeprecated(
- unsafe_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr,
- &error_msg, &error_line, &error_column);
- if (value) {
- success_callback.Run(std::move(value));
- } else {
- error_callback.Run(base::StringPrintf(
- "%s (%d:%d)", error_msg.c_str(), error_line, error_column));
- }
- },
- unsafe_json, success_callback, error_callback));
-}
-
-} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/json_unsafe_parser.h b/chromium/components/ntp_tiles/json_unsafe_parser.h
deleted file mode 100644
index 4a5a1f47dcd..00000000000
--- a/chromium/components/ntp_tiles/json_unsafe_parser.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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_NTP_TILES_JSON_UNSAFE_PARSER_H_
-#define COMPONENTS_NTP_TILES_JSON_UNSAFE_PARSER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-
-namespace base {
-class Value;
-}
-
-namespace ntp_tiles {
-
-// Mimics SafeJsonParser, but parses unsafely.
-//
-// Do not use this class, unless you can't help it. On most platforms,
-// SafeJsonParser is available and is safer. If it is not available (e.g. on
-// iOS), then this class mimics its API without its safety.
-class JsonUnsafeParser {
- public:
- using SuccessCallback = base::Callback<void(std::unique_ptr<base::Value>)>;
- using ErrorCallback = base::Callback<void(const std::string&)>;
-
- // As with SafeJsonParser, runs either success_callback or error_callback on
- // the calling thread, but not before the call returns.
- static void Parse(const std::string& unsafe_json,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback);
-
- JsonUnsafeParser() = delete;
-};
-
-} // namespace ntp_tiles
-
-#endif // COMPONENTS_NTP_TILES_POPULAR_SITES_H_
diff --git a/chromium/components/ntp_tiles/metrics.cc b/chromium/components/ntp_tiles/metrics.cc
index 9cc76163918..8b97fa2fe9d 100644
--- a/chromium/components/ntp_tiles/metrics.cc
+++ b/chromium/components/ntp_tiles/metrics.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "components/ntp_tiles/constants.h"
#include "components/rappor/public/rappor_utils.h"
namespace ntp_tiles {
@@ -16,9 +17,6 @@ namespace metrics {
namespace {
-// Maximum number of tiles to record in histograms.
-const int kMaxNumTiles = 12;
-
const int kLastTitleSource = static_cast<int>(TileTitleSource::LAST);
// Identifiers for the various tile sources.
@@ -29,6 +27,7 @@ const char kHistogramBakedInName[] = "popular_baked_in";
const char kHistogramWhitelistName[] = "whitelist";
const char kHistogramHomepageName[] = "homepage";
const char kHistogramCustomLinksName[] = "custom_links";
+const char kHistogramExploreName[] = "explore";
const char kHistogramSearchName[] = "search_page";
// Suffixes for the various icon types.
@@ -60,6 +59,8 @@ std::string GetSourceHistogramName(TileSource source) {
return kHistogramHomepageName;
case TileSource::CUSTOM_LINKS:
return kHistogramCustomLinksName;
+ case TileSource::EXPLORE:
+ return kHistogramExploreName;
case TileSource::SEARCH_PAGE:
return kHistogramSearchName;
}
diff --git a/chromium/components/ntp_tiles/most_visited_sites.cc b/chromium/components/ntp_tiles/most_visited_sites.cc
index e643df1701a..e4744670b75 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <iterator>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -37,10 +38,6 @@ namespace ntp_tiles {
namespace {
-// The maximum number of custom links that can be shown. This is independent of
-// the maximum number of Most Visited sites that can be shown.
-const size_t kMaxNumCustomLinks = 10;
-
const base::Feature kDisplaySuggestionsServiceTiles{
"DisplaySuggestionsServiceTiles", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -60,11 +57,9 @@ const char* kKnownGenericPagePrefixes[] = {
""}; // The no-www domain matches domains on same level .
// Determine whether we need any tiles from PopularSites to fill up a grid of
-// |num_tiles| tiles. If exploration sections are used, we need popular sites
-// regardless of how many tiles we already have.
+// |num_tiles| tiles.
bool NeedPopularSites(const PrefService* prefs, int num_tiles) {
- return base::FeatureList::IsEnabled(kSiteExplorationUiFeature) ||
- prefs->GetInteger(prefs::kNumPersonalTiles) < num_tiles;
+ return prefs->GetInteger(prefs::kNumPersonalTiles) < num_tiles;
}
bool AreURLsEquivalent(const GURL& url1, const GURL& url2) {
@@ -189,6 +184,8 @@ bool MostVisitedSites::DoesSourceExist(TileSource source) const {
return supervisor_ != nullptr;
case TileSource::CUSTOM_LINKS:
return custom_links_ != nullptr;
+ case TileSource::EXPLORE:
+ return explore_sites_client_ != nullptr;
case TileSource::SEARCH_PAGE:
#if !defined(OS_ANDROID) && !defined(OS_IOS)
return true;
@@ -206,6 +203,11 @@ void MostVisitedSites::SetHomepageClient(
homepage_client_ = std::move(client);
}
+void MostVisitedSites::SetExploreSitesClient(
+ std::unique_ptr<ExploreSitesClient> client) {
+ explore_sites_client_ = std::move(client);
+}
+
void MostVisitedSites::SetMostVisitedURLsObserver(Observer* observer,
size_t num_sites) {
DCHECK(observer);
@@ -295,6 +297,7 @@ bool MostVisitedSites::AddCustomLink(const GURL& url,
if (!custom_links_ || !custom_links_enabled_)
return false;
+ bool is_first_action = !custom_links_->IsInitialized();
// Initialize custom links if they have not been initialized yet.
InitializeCustomLinks();
@@ -303,6 +306,10 @@ bool MostVisitedSites::AddCustomLink(const GURL& url,
if (custom_links_action_count_ != -1)
custom_links_action_count_++;
BuildCurrentTiles();
+ } else if (is_first_action) {
+ // We don't want to keep custom links initialized if the first action after
+ // initialization failed.
+ UninitializeCustomLinks();
}
return success;
}
@@ -313,6 +320,7 @@ bool MostVisitedSites::UpdateCustomLink(const GURL& url,
if (!custom_links_ || !custom_links_enabled_)
return false;
+ bool is_first_action = !custom_links_->IsInitialized();
// Initialize custom links if they have not been initialized yet.
InitializeCustomLinks();
@@ -321,6 +329,10 @@ bool MostVisitedSites::UpdateCustomLink(const GURL& url,
if (custom_links_action_count_ != -1)
custom_links_action_count_++;
BuildCurrentTiles();
+ } else if (is_first_action) {
+ // We don't want to keep custom links initialized if the first action after
+ // initialization failed.
+ UninitializeCustomLinks();
}
return success;
}
@@ -329,6 +341,7 @@ bool MostVisitedSites::ReorderCustomLink(const GURL& url, size_t new_pos) {
if (!custom_links_ || !custom_links_enabled_)
return false;
+ bool is_first_action = !custom_links_->IsInitialized();
// Initialize custom links if they have not been initialized yet.
InitializeCustomLinks();
@@ -337,6 +350,10 @@ bool MostVisitedSites::ReorderCustomLink(const GURL& url, size_t new_pos) {
if (custom_links_action_count_ != -1)
custom_links_action_count_++;
BuildCurrentTiles();
+ } else if (is_first_action) {
+ // We don't want to keep custom links initialized if the first action after
+ // initialization failed.
+ UninitializeCustomLinks();
}
return success;
}
@@ -345,6 +362,7 @@ bool MostVisitedSites::DeleteCustomLink(const GURL& url) {
if (!custom_links_ || !custom_links_enabled_)
return false;
+ bool is_first_action = !custom_links_->IsInitialized();
// Initialize custom links if they have not been initialized yet.
InitializeCustomLinks();
@@ -353,6 +371,10 @@ bool MostVisitedSites::DeleteCustomLink(const GURL& url) {
if (custom_links_action_count_ != -1)
custom_links_action_count_++;
BuildCurrentTiles();
+ } else if (is_first_action) {
+ // We don't want to keep custom links initialized if the first action after
+ // initialization failed.
+ UninitializeCustomLinks();
}
return success;
}
@@ -707,6 +729,19 @@ NTPTilesVector MostVisitedSites::InsertHomeTile(
return new_tiles;
}
+base::Optional<NTPTile> MostVisitedSites::CreateExploreSitesTile() {
+ if (!explore_sites_client_)
+ return base::nullopt;
+
+ NTPTile explore_sites_tile;
+ explore_sites_tile.url = explore_sites_client_->GetExploreSitesUrl();
+ explore_sites_tile.title = explore_sites_client_->GetExploreSitesTitle();
+ explore_sites_tile.source = TileSource::EXPLORE;
+ explore_sites_tile.title_source = TileTitleSource::UNKNOWN;
+
+ return explore_sites_tile;
+}
+
NTPTilesVector MostVisitedSites::InsertSearchTile(NTPTilesVector tiles) const {
DCHECK_GT(max_num_sites_, 0u);
@@ -771,6 +806,8 @@ void MostVisitedSites::BuildCustomLinks(
DCHECK(custom_links_);
NTPTilesVector tiles;
+ // The maximum number of custom links that can be shown is independent of the
+ // maximum number of Most Visited sites that can be shown.
size_t num_tiles = std::min(links.size(), kMaxNumCustomLinks);
for (size_t i = 0; i < num_tiles; ++i) {
const CustomLinksManager::Link& link = links.at(i);
@@ -813,7 +850,15 @@ void MostVisitedSites::InitiateNotificationForNewTiles(
void MostVisitedSites::MergeMostVisitedTiles(NTPTilesVector personal_tiles) {
std::set<std::string> used_hosts;
- size_t num_actual_tiles = 0u;
+
+ base::Optional<NTPTile> explore_tile = CreateExploreSitesTile();
+ size_t num_actual_tiles = explore_tile ? 1 : 0;
+
+ // The explore sites tile may have taken a space that was utilized by the
+ // personal tiles.
+ if (personal_tiles.size() + num_actual_tiles > max_num_sites_) {
+ personal_tiles.pop_back();
+ }
AddToHostsAndTotalCount(personal_tiles, &used_hosts, &num_actual_tiles);
NTPTilesVector whitelist_tiles =
@@ -827,7 +872,7 @@ void MostVisitedSites::MergeMostVisitedTiles(NTPTilesVector personal_tiles) {
NTPTilesVector new_tiles =
MergeTiles(std::move(personal_tiles), std::move(whitelist_tiles),
- std::move(sections[SectionType::PERSONALIZED]));
+ std::move(sections[SectionType::PERSONALIZED]), explore_tile);
SaveTilesAndNotify(std::move(new_tiles), std::move(sections));
}
@@ -854,9 +899,11 @@ void MostVisitedSites::SaveTilesAndNotify(
}
// static
-NTPTilesVector MostVisitedSites::MergeTiles(NTPTilesVector personal_tiles,
- NTPTilesVector whitelist_tiles,
- NTPTilesVector popular_tiles) {
+NTPTilesVector MostVisitedSites::MergeTiles(
+ NTPTilesVector personal_tiles,
+ NTPTilesVector whitelist_tiles,
+ NTPTilesVector popular_tiles,
+ base::Optional<NTPTile> explore_tile) {
NTPTilesVector merged_tiles;
std::move(personal_tiles.begin(), personal_tiles.end(),
std::back_inserter(merged_tiles));
@@ -864,6 +911,9 @@ NTPTilesVector MostVisitedSites::MergeTiles(NTPTilesVector personal_tiles,
std::back_inserter(merged_tiles));
std::move(popular_tiles.begin(), popular_tiles.end(),
std::back_inserter(merged_tiles));
+ if (explore_tile)
+ merged_tiles.push_back(*explore_tile);
+
return merged_tiles;
}
diff --git a/chromium/components/ntp_tiles/most_visited_sites.h b/chromium/components/ntp_tiles/most_visited_sites.h
index edcb280a039..e2e349e2a0f 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.h
+++ b/chromium/components/ntp_tiles/most_visited_sites.h
@@ -113,6 +113,13 @@ class MostVisitedSites : public history::TopSitesObserver,
virtual void QueryHomepageTitle(TitleCallback title_callback) = 0;
};
+ class ExploreSitesClient {
+ public:
+ virtual ~ExploreSitesClient() = default;
+ virtual GURL GetExploreSitesUrl() const = 0;
+ virtual base::string16 GetExploreSitesTitle() const = 0;
+ };
+
// Construct a MostVisitedSites instance.
//
// |prefs| and |suggestions| are required and may not be null. |top_sites|,
@@ -152,6 +159,10 @@ class MostVisitedSites : public history::TopSitesObserver,
// |client| must not be null and outlive this object.
void SetHomepageClient(std::unique_ptr<HomepageClient> client);
+ // Sets the client that provides the Explore Sites tile. Can be null if no
+ // such tile is desirable.
+ void SetExploreSitesClient(std::unique_ptr<ExploreSitesClient> client);
+
// Requests an asynchronous refresh of the suggestions. Notifies the observer
// if the request resulted in the set of tiles changing.
void Refresh();
@@ -176,24 +187,25 @@ class MostVisitedSites : public history::TopSitesObserver,
void EnableCustomLinks(bool enable);
// Adds a custom link. If the number of current links is maxed, returns false
// and does nothing. Will initialize custom links if they have not been
- // initialized yet. Custom links must be enabled.
+ // initialized yet, unless the action fails. Custom links must be enabled.
bool AddCustomLink(const GURL& url, const base::string16& title);
// Updates the URL and/or title of the custom link specified by |url|. If
// |url| does not exist or |new_url| already exists in the custom link list,
// returns false and does nothing. Will initialize custom links if they have
- // not been initialized yet. Custom links must be enabled.
+ // not been initialized yet, unless the action fails. Custom links must be
+ // enabled.
bool UpdateCustomLink(const GURL& url,
const GURL& new_url,
const base::string16& new_title);
// Moves the custom link specified by |url| to the index |new_pos|. If |url|
// does not exist, or |new_pos| is invalid, returns false and does nothing.
- // Will initialize custom links if they have not been initialized yet. Custom
- // links must be enabled.
+ // Will initialize custom links if they have not been initialized yet, unless
+ // the action fails. Custom links must be enabled.
bool ReorderCustomLink(const GURL& url, size_t new_pos);
// Deletes the custom link with the specified |url|. If |url| does not exist
// in the custom link list, returns false and does nothing. Will initialize
- // custom links if they have not been initialized yet. Custom links must be
- // enabled.
+ // custom links if they have not been initialized yet, unless the action
+ // fails. Custom links must be enabled.
bool DeleteCustomLink(const GURL& url);
// Restores the previous state of custom links before the last action that
// modified them. If there was no action, does nothing. If this is undoing the
@@ -213,7 +225,8 @@ class MostVisitedSites : public history::TopSitesObserver,
// public method for ease of testing.
static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles,
NTPTilesVector whitelist_tiles,
- NTPTilesVector popular_tiles);
+ NTPTilesVector popular_tiles,
+ base::Optional<NTPTile> explore_tile);
private:
FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
@@ -309,6 +322,10 @@ class MostVisitedSites : public history::TopSitesObserver,
NTPTilesVector InsertHomeTile(NTPTilesVector tiles,
const base::string16& title) const;
+ // Creates a tile for the Explore Sites page, if enabled. The tile is added to
+ // the front of the list.
+ base::Optional<NTPTile> CreateExploreSitesTile();
+
// Adds the Google Search page as first tile to |tiles| and returns them as
// new vector. Drops existing tiles with the same host as the Google Search
// page and tiles that would exceed the maximum.
@@ -333,6 +350,7 @@ class MostVisitedSites : public history::TopSitesObserver,
std::unique_ptr<IconCacher> const icon_cacher_;
std::unique_ptr<MostVisitedSitesSupervisor> supervisor_;
std::unique_ptr<HomepageClient> homepage_client_;
+ std::unique_ptr<ExploreSitesClient> explore_sites_client_;
Observer* observer_;
diff --git a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
index fe08f7a1442..129a07c789f 100644
--- a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -27,16 +27,15 @@
#include "build/build_config.h"
#include "components/history/core/browser/top_sites.h"
#include "components/history/core/browser/top_sites_observer.h"
-#include "components/ntp_tiles/constants.h"
#include "components/ntp_tiles/custom_links_manager.h"
#include "components/ntp_tiles/features.h"
#include "components/ntp_tiles/icon_cacher.h"
-#include "components/ntp_tiles/json_unsafe_parser.h"
#include "components/ntp_tiles/popular_sites_impl.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/section_type.h"
#include "components/ntp_tiles/switches.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "services/data_decoder/public/cpp/testing_json_parser.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -83,6 +82,8 @@ using testing::_;
const char kHomepageUrl[] = "http://ho.me/";
const char kHomepageTitle[] = "Home";
+const char kTestExploreUrl[] = "https://example.com/";
+const char kTestExploreTitle[] = "Example";
std::string PrintTile(const std::string& title,
const std::string& url,
@@ -102,6 +103,29 @@ MATCHER_P3(MatchesTile, title, url, source, PrintTile(title, url, source)) {
arg.source == source;
}
+std::string PrintTileSource(TileSource source) {
+ return std::string("has source ") +
+ testing::PrintToString(static_cast<int>(source));
+}
+
+MATCHER_P(TileWithSource, source, PrintTileSource(source)) {
+ return arg.source == source;
+}
+
+MATCHER_P3(LastTileIs,
+ title,
+ url,
+ source,
+ std::string("last tile ") + PrintTile(title, url, source)) {
+ const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
+ if (tiles.empty())
+ return false;
+
+ const NTPTile& last = tiles.back();
+ return last.title == base::ASCIIToUTF16(title) && last.url == GURL(url) &&
+ last.source == source;
+}
+
MATCHER_P3(FirstPersonalizedTileIs,
title,
url,
@@ -243,6 +267,17 @@ class FakeHomepageClient : public MostVisitedSites::HomepageClient {
base::Optional<base::string16> homepage_title_;
};
+class FakeExploreSitesClient : public MostVisitedSites::ExploreSitesClient {
+ public:
+ ~FakeExploreSitesClient() override = default;
+
+ GURL GetExploreSitesUrl() const override { return GURL(kTestExploreUrl); }
+
+ base::string16 GetExploreSitesTitle() const override {
+ return base::ASCIIToUTF16(kTestExploreTitle);
+ }
+};
+
class MockIconCacher : public IconCacher {
public:
MOCK_METHOD3(StartFetchPopularSites,
@@ -299,7 +334,7 @@ class PopularSitesFactoryForTest {
"title": "PopularSite2",
"url": "http://popularsite2/",
"favicon_url": "http://popularsite2/favicon.ico"
- },
+ }
])");
test_url_loader_factory_.AddResponse(
@@ -316,7 +351,7 @@ class PopularSitesFactoryForTest {
"title": "Google News",
"url": "http://news.google.com",
"favicon_url": "http://news.google.com/favicon.ico"
- },
+ }
])");
test_url_loader_factory_.AddResponse(
@@ -370,7 +405,7 @@ class PopularSitesFactoryForTest {
prefs_,
/*template_url_service=*/nullptr,
/*variations_service=*/nullptr, test_shared_loader_factory_,
- base::Bind(JsonUnsafeParser::Parse));
+ base::Bind(&data_decoder::SafeJsonParser::Parse, nullptr));
}
private:
@@ -502,6 +537,13 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
return raw_client_ptr;
}
+ FakeExploreSitesClient* RegisterNewExploreSitesClient() {
+ auto explore_sites_client = std::make_unique<FakeExploreSitesClient>();
+ FakeExploreSitesClient* raw_client_ptr = explore_sites_client.get();
+ most_visited_sites_->SetExploreSitesClient(std::move(explore_sites_client));
+ return raw_client_ptr;
+ }
+
void DisableRemoteSuggestions() {
EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
.Times(AnyNumber())
@@ -523,6 +565,7 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
TopSitesCallbackList top_sites_callbacks_;
base::test::ScopedTaskEnvironment task_environment_;
+ data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
PopularSitesFactoryForTest popular_sites_factory_;
scoped_refptr<StrictMock<MockTopSites>> mock_top_sites_;
@@ -867,6 +910,71 @@ TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlacklistingUndone) {
base::RunLoop().RunUntilIdle();
}
+TEST_P(MostVisitedSitesTest, ShouldNotIncludeTileForExploreSitesIfNoClient) {
+ // Does not register an explore sites client.
+
+ DisableRemoteSuggestions();
+ EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
+ .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
+ MakeMostVisitedURL("ESPN", "http://espn.com/"),
+ MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
+ EXPECT_CALL(mock_observer_,
+ OnURLsAvailable(Not(Contains(
+ Pair(SectionType::PERSONALIZED,
+ Contains(TileWithSource(TileSource::EXPLORE)))))));
+ // Note that 5 sites are requested, this means that there should be the 3 from
+ // top sites and two from popular sites.
+ most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
+ /*num_sites=*/5);
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests that the explore sites tile appears when there is a mix of top sites
+// and popular sites.
+TEST_P(MostVisitedSitesTest, ShouldIncludeTileForExploreSites) {
+ RegisterNewExploreSitesClient();
+ DisableRemoteSuggestions();
+ EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
+ .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
+ MakeMostVisitedURL("ESPN", "http://espn.com/"),
+ MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
+ EXPECT_CALL(mock_observer_,
+ OnURLsAvailable(LastTileIs(kTestExploreTitle, kTestExploreUrl,
+ TileSource::EXPLORE)));
+ // Note that 5 sites are requested, this means that there should be the 3 from
+ // top sites, one from popular sites, and one explore tile.
+ most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
+ /*num_sites=*/5);
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_P(MostVisitedSitesTest, RemovesPersonalSiteIfExploreSitesTilePresent) {
+ RegisterNewExploreSitesClient();
+ DisableRemoteSuggestions();
+ EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
+ .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
+ MakeMostVisitedURL("ESPN", "http://espn.com/"),
+ MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
+ EXPECT_CALL(mock_observer_,
+ OnURLsAvailable(Contains(Pair(
+ SectionType::PERSONALIZED,
+ ElementsAre(MatchesTile("ESPN", "http://espn.com/",
+ TileSource::TOP_SITES),
+ MatchesTile("Mobile", "http://m.mobile.de/",
+ TileSource::TOP_SITES),
+ MatchesTile(kTestExploreTitle, kTestExploreUrl,
+ TileSource::EXPLORE))))));
+ most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
+ /*num_sites=*/3);
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_P(MostVisitedSitesTest, ShouldInformSuggestionSourcesWhenBlacklisting) {
EXPECT_CALL(*mock_top_sites_, AddBlacklistedURL(Eq(GURL(kHomepageUrl))))
.Times(1);
@@ -883,51 +991,6 @@ TEST_P(MostVisitedSitesTest, ShouldInformSuggestionSourcesWhenBlacklisting) {
/*add_url=*/false);
}
-TEST_P(MostVisitedSitesTest, ShouldContainSiteExplorationsWhenFeatureEnabled) {
- base::test::ScopedFeatureList feature_list;
- std::map<SectionType, NTPTilesVector> sections;
- feature_list.InitAndEnableFeature(kSiteExplorationUiFeature);
- pref_service_.SetString(prefs::kPopularSitesOverrideVersion, "6");
- RecreateMostVisitedSites(); // Refills cache with version 6 popular sites.
- DisableRemoteSuggestions();
- EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
- .WillRepeatedly(InvokeCallbackArgument<0>(
- MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")}));
- EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
- EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
- .WillOnce(SaveArg<0>(&sections));
-
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
- base::RunLoop().RunUntilIdle();
-
- if (!IsPopularSitesFeatureEnabled()) {
- EXPECT_THAT(
- sections,
- Contains(Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
- TileSource::TOP_SITES)))));
- return;
- }
- const auto& expected_sections =
- most_visited_sites_->popular_sites()->sections();
- ASSERT_THAT(expected_sections.size(), Ge(2ul));
- EXPECT_THAT(sections.size(), Eq(expected_sections.size()));
- EXPECT_THAT(
- sections,
- AllOf(Contains(Pair(
- SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
- TileSource::TOP_SITES),
- MatchesTile("PopularSite1", "http://popularsite1/",
- TileSource::POPULAR),
- MatchesTile("PopularSite2", "http://popularsite2/",
- TileSource::POPULAR)))),
- Contains(Pair(SectionType::NEWS, SizeIs(2ul))),
- Contains(Pair(SectionType::SOCIAL, SizeIs(1ul))),
- Contains(Pair(_, IsEmpty()))));
-}
-
TEST_P(MostVisitedSitesTest,
ShouldDeduplicatePopularSitesWithMostVisitedIffHostAndTitleMatches) {
pref_service_.SetString(prefs::kPopularSitesOverrideCountry, "US");
@@ -1515,7 +1578,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
// Complete a second custom link action.
EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(false));
EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(true));
- EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
+ EXPECT_CALL(*mock_custom_links_, IsInitialized())
+ .WillRepeatedly(Return(true));
EXPECT_CALL(*mock_custom_links_, GetLinks())
.WillOnce(ReturnRef(expected_links));
most_visited_sites_->DeleteCustomLink(GURL("test.com"));
@@ -1531,6 +1595,73 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
base::RunLoop().RunUntilIdle();
}
+TEST_P(MostVisitedSitesWithCustomLinksTest,
+ UninitializeCustomLinksIfFirstActionFails) {
+ const char kTestUrl[] = "http://site1/";
+ const char kTestTitle[] = "Site 1";
+ std::vector<CustomLinksManager::Link> expected_links(
+ {CustomLinksManager::Link{GURL(kTestUrl),
+ base::UTF8ToUTF16(kTestTitle)}});
+ std::map<SectionType, NTPTilesVector> sections;
+ DisableRemoteSuggestions();
+
+ // Build initial tiles with Top Sites.
+ EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+ ExpectBuildWithTopSites(
+ MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
+ most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
+ /*num_sites=*/1);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_THAT(
+ sections.at(SectionType::PERSONALIZED),
+ ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
+
+ // Fail to add a custom link. This should not initialize custom links nor
+ // notify.
+ EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+ EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(false));
+ EXPECT_CALL(*mock_custom_links_, IsInitialized())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_custom_links_, Uninitialize());
+ EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
+ most_visited_sites_->AddCustomLink(GURL(kTestUrl), base::UTF8ToUTF16("test"));
+ base::RunLoop().RunUntilIdle();
+
+ // Fail to edit a custom link. This should not initialize custom links nor
+ // notify.
+ EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+ EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(false));
+ EXPECT_CALL(*mock_custom_links_, IsInitialized())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_custom_links_, Uninitialize());
+ EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
+ most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test2.com"),
+ base::UTF8ToUTF16("test"));
+ base::RunLoop().RunUntilIdle();
+
+ // Fail to reorder a custom link. This should not initialize custom links nor
+ // notify.
+ EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+ EXPECT_CALL(*mock_custom_links_, ReorderLink(_, _)).WillOnce(Return(false));
+ EXPECT_CALL(*mock_custom_links_, IsInitialized())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_custom_links_, Uninitialize());
+ EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
+ most_visited_sites_->ReorderCustomLink(GURL("test.com"), 1);
+ base::RunLoop().RunUntilIdle();
+
+ // Fail to delete a custom link. This should not initialize custom links nor
+ // notify.
+ EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+ EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(false));
+ EXPECT_CALL(*mock_custom_links_, IsInitialized())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_custom_links_, Uninitialize());
+ EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
+ most_visited_sites_->DeleteCustomLink(GURL("test.com"));
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_P(MostVisitedSitesWithCustomLinksTest, RebuildTilesOnCustomLinksChanged) {
const char kTestUrl1[] = "http://site1/";
const char kTestUrl2[] = "http://site2/";
@@ -2062,7 +2193,8 @@ TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPersonalOnly) {
// tiles.
EXPECT_THAT(MostVisitedSites::MergeTiles(std::move(personal_tiles),
/*whitelist_tiles=*/NTPTilesVector(),
- /*popular_tiles=*/NTPTilesVector()),
+ /*popular_tiles=*/NTPTilesVector(),
+ /*explore_tile=*/base::nullopt),
ElementsAre(MatchesTile("Site 1", "https://www.site1.com/",
TileSource::TOP_SITES),
MatchesTile("Site 2", "https://www.site2.com/",
@@ -2085,7 +2217,8 @@ TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPopularOnly) {
EXPECT_THAT(
MostVisitedSites::MergeTiles(/*personal_tiles=*/NTPTilesVector(),
/*whitelist_tiles=*/NTPTilesVector(),
- /*popular_tiles=*/std::move(popular_tiles)),
+ /*popular_tiles=*/std::move(popular_tiles),
+ /*explore_tile=*/base::nullopt),
ElementsAre(
MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
@@ -2103,18 +2236,23 @@ TEST(MostVisitedSitesMergeTest, ShouldMergeTilesFavoringPersonalOverPopular) {
MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
};
+ base::Optional<NTPTile> explore_tile{
+ MakeTile("Explore", "https://explore.example.com/", TileSource::EXPLORE),
+ };
EXPECT_THAT(
MostVisitedSites::MergeTiles(std::move(personal_tiles),
/*whitelist_tiles=*/NTPTilesVector(),
- /*popular_tiles=*/std::move(popular_tiles)),
+ /*popular_tiles=*/std::move(popular_tiles),
+ /*explore_tiles=*/explore_tile),
ElementsAre(
MatchesTile("Site 3", "https://www.site3.com/",
TileSource::TOP_SITES),
MatchesTile("Site 4", "https://www.site4.com/",
TileSource::TOP_SITES),
MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
- MatchesTile("Site 2", "https://www.site2.com/",
- TileSource::POPULAR)));
+ MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
+ MatchesTile("Explore", "https://explore.example.com/",
+ TileSource::EXPLORE)));
}
#if !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chromium/components/ntp_tiles/popular_sites_impl.cc b/chromium/components/ntp_tiles/popular_sites_impl.cc
index 02380d5d43a..34eef87fd84 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl.cc
@@ -19,9 +19,8 @@
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/google/core/common/google_util.h"
-#include "components/ntp_tiles/constants.h"
+#include "components/ntp_tiles/features.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/switches.h"
#include "components/pref_registry/pref_registry_syncable.h"
@@ -172,9 +171,10 @@ std::map<SectionType, PopularSites::SitesVector> ParseVersion6OrAbove(
<< "invalid ID (" << section << ")";
continue;
}
+ // Non-personalized site exploration tiles are no longer supported, so
+ // ignore all other section types.
SectionType section_type = static_cast<SectionType>(section);
- if (section_type == SectionType::UNKNOWN) {
- LOG(WARNING) << "Dropped an unknown section in SitesExploration list.";
+ if (section_type != SectionType::PERSONALIZED) {
continue;
}
const base::ListValue* sites_list;
@@ -183,12 +183,6 @@ std::map<SectionType, PopularSites::SitesVector> ParseVersion6OrAbove(
}
sections[section_type] = ParseSiteList(*sites_list);
}
- if (!base::FeatureList::IsEnabled(kSiteExplorationUiFeature)) {
- // New versions of popular sites that should act like old versions will
- // mimic having only the personalized list.
- return {std::make_pair(SectionType::PERSONALIZED,
- std::move(sections[SectionType::PERSONALIZED]))};
- }
return sections;
}
@@ -268,12 +262,12 @@ PopularSitesImpl::PopularSitesImpl(
const TemplateURLService* template_url_service,
VariationsService* variations_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- ParseJSONCallback parse_json)
+ const ParseJSONCallback& parse_json)
: prefs_(prefs),
template_url_service_(template_url_service),
variations_(variations_service),
url_loader_factory_(std::move(url_loader_factory)),
- parse_json_(std::move(parse_json)),
+ parse_json_(parse_json),
is_fallback_(false),
sections_(
ParseSites(*prefs->GetList(prefs::kPopularSitesJsonPref),
@@ -450,11 +444,7 @@ void PopularSitesImpl::FetchPopularSites() {
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = pending_url_;
- resource_request->load_flags =
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
- // TODO(https://crbug.com/808498): Re-add data use measurement once
- // SimpleURLLoader supports it.
- // ID=data_use_measurement::DataUseUserData::NTP_TILES
+ resource_request->allow_credentials = false;
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
simple_url_loader_->SetRetryOptions(
@@ -475,15 +465,15 @@ void PopularSitesImpl::OnSimpleLoaderComplete(
}
parse_json_.Run(*response_body,
- base::Bind(&PopularSitesImpl::OnJsonParsed,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&PopularSitesImpl::OnJsonParseFailed,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&PopularSitesImpl::OnJsonParsed,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::BindOnce(&PopularSitesImpl::OnJsonParseFailed,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void PopularSitesImpl::OnJsonParsed(std::unique_ptr<base::Value> json) {
+void PopularSitesImpl::OnJsonParsed(base::Value json) {
std::unique_ptr<base::ListValue> list =
- base::ListValue::From(std::move(json));
+ base::ListValue::From(base::Value::ToUniquePtrValue(std::move(json)));
if (!list) {
DLOG(WARNING) << "JSON is not a list";
OnDownloadFailed();
diff --git a/chromium/components/ntp_tiles/popular_sites_impl.h b/chromium/components/ntp_tiles/popular_sites_impl.h
index 43588d01250..5b51e289ccb 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl.h
+++ b/chromium/components/ntp_tiles/popular_sites_impl.h
@@ -39,10 +39,10 @@ class TemplateURLService;
namespace ntp_tiles {
-using ParseJSONCallback = base::Callback<void(
+using ParseJSONCallback = base::RepeatingCallback<void(
const std::string& unsafe_json,
- const base::Callback<void(std::unique_ptr<base::Value>)>& success_callback,
- const base::Callback<void(const std::string&)>& error_callback)>;
+ base::OnceCallback<void(base::Value)> success_callback,
+ base::OnceCallback<void(const std::string&)> error_callback)>;
// Actual (non-test) implementation of the PopularSites interface. Caches the
// downloaded file on disk to avoid re-downloading on every startup.
@@ -53,7 +53,7 @@ class PopularSitesImpl : public PopularSites {
const TemplateURLService* template_url_service,
variations::VariationsService* variations_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- ParseJSONCallback parse_json);
+ const ParseJSONCallback& parse_json);
~PopularSitesImpl() override;
@@ -80,7 +80,7 @@ class PopularSitesImpl : public PopularSites {
// Called once SimpleURLLoader completes the network request.
void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
- void OnJsonParsed(std::unique_ptr<base::Value> json);
+ void OnJsonParsed(base::Value json);
void OnJsonParseFailed(const std::string& error_message);
void OnDownloadFailed();
diff --git a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
index b3b88f61882..b965d6b611d 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -22,13 +22,13 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/ntp_tiles/constants.h"
-#include "components/ntp_tiles/json_unsafe_parser.h"
+#include "components/ntp_tiles/features.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/tile_source.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "net/http/http_status_code.h"
+#include "services/data_decoder/public/cpp/testing_json_parser.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -204,7 +204,7 @@ class PopularSitesTest : public ::testing::Test {
prefs_.get(),
/*template_url_service=*/nullptr,
/*variations_service=*/nullptr, test_shared_loader_factory_,
- base::Bind(JsonUnsafeParser::Parse));
+ base::Bind(&data_decoder::SafeJsonParser::Parse, nullptr));
}
const TestPopularSite kWikipedia;
@@ -213,6 +213,7 @@ class PopularSitesTest : public ::testing::Test {
base::test::ScopedTaskEnvironment task_environment_{
base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_;
std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
@@ -531,10 +532,7 @@ TEST_F(PopularSitesTest, ShouldOverrideDirectory) {
EXPECT_THAT(sites.size(), Eq(1u));
}
-TEST_F(PopularSitesTest, DoesNotFetchExplorationSitesWithoutFeature) {
- base::test::ScopedFeatureList override_features;
- override_features.InitAndDisableFeature(kSiteExplorationUiFeature);
-
+TEST_F(PopularSitesTest, DoesNotFetchExplorationSites) {
SetCountryAndVersion("ZZ", "6");
RespondWithV6JSON(
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_6.json",
@@ -549,46 +547,5 @@ TEST_F(PopularSitesTest, DoesNotFetchExplorationSitesWithoutFeature) {
EXPECT_THAT(sections, Not(Contains(Pair(SectionType::NEWS, _))));
}
-TEST_F(PopularSitesTest, FetchesExplorationSitesWithFeature) {
- base::test::ScopedFeatureList override_features;
- override_features.InitAndEnableFeature(kSiteExplorationUiFeature);
- SetCountryAndVersion("ZZ", "6");
- RespondWithV6JSON(
- "https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_6.json",
- {{SectionType::PERSONALIZED, {kChromium}},
- {SectionType::ENTERTAINMENT, {kWikipedia, kYouTube}},
- {SectionType::NEWS, {kYouTube}},
- {SectionType::TOOLS, TestPopularSiteVector{}}});
-
- std::map<SectionType, PopularSites::SitesVector> sections;
- EXPECT_THAT(FetchAllSections(/*force_download=*/false, &sections),
- Eq(base::Optional<bool>(true)));
-
- EXPECT_THAT(sections, ElementsAre(Pair(SectionType::PERSONALIZED, SizeIs(1)),
- Pair(SectionType::ENTERTAINMENT, SizeIs(2)),
- Pair(SectionType::NEWS, SizeIs(1)),
- Pair(SectionType::TOOLS, IsEmpty())));
-}
-
-TEST_F(PopularSitesTest, FetchesExplorationSitesIgnoreUnknownSections) {
- base::test::ScopedFeatureList override_features;
- override_features.InitAndEnableFeature(kSiteExplorationUiFeature);
-
- SetCountryAndVersion("ZZ", "6");
- RespondWithV6JSON(
- "https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_6.json",
- {{SectionType::UNKNOWN, {kChromium}},
- {SectionType::NEWS, {kYouTube}},
- {SectionType::UNKNOWN, {kWikipedia, kYouTube}}});
-
- std::map<SectionType, PopularSites::SitesVector> sections;
- EXPECT_THAT(FetchAllSections(/*force_download=*/false, &sections),
- Eq(base::Optional<bool>(true)));
-
- // Expect that there are four sections, none of which is empty.
- EXPECT_THAT(sections, ElementsAre(Pair(SectionType::PERSONALIZED, SizeIs(0)),
- Pair(SectionType::NEWS, SizeIs(1))));
-}
-
} // namespace
} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/tile_source.h b/chromium/components/ntp_tiles/tile_source.h
index 689411b4302..899e94c9f8c 100644
--- a/chromium/components/ntp_tiles/tile_source.h
+++ b/chromium/components/ntp_tiles/tile_source.h
@@ -26,6 +26,8 @@ enum class TileSource {
WHITELIST,
// Tile containing the user-set home page is replacing the home page button.
HOMEPAGE,
+ // Tile comes from explore sites list.
+ EXPLORE,
// Tile containing the Google Search page.
SEARCH_PAGE,
diff --git a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
index fdbadcbc115..0ba8febaa8a 100644
--- a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
+++ b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
@@ -18,6 +18,7 @@
#include "base/task_runner_util.h"
#include "base/values.h"
#include "components/favicon/core/favicon_service.h"
+#include "components/ntp_tiles/constants.h"
#include "components/ntp_tiles/most_visited_sites.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/webui/ntp_tiles_internals_message_handler_client.h"
@@ -58,9 +59,7 @@ NTPTilesInternalsMessageHandler::NTPTilesInternalsMessageHandler(
favicon::FaviconService* favicon_service)
: favicon_service_(favicon_service),
client_(nullptr),
- // 9 tiles are required for the custom links feature in order to balance
- // the Most Visited rows (this is due to an additional "Add" button).
- site_count_(9),
+ site_count_(ntp_tiles::kMaxNumMostVisited),
weak_ptr_factory_(this) {}
NTPTilesInternalsMessageHandler::~NTPTilesInternalsMessageHandler() = default;