Commit 1eca54dd authored by Natalie Chouinard's avatar Natalie Chouinard Committed by Commit Bot

[Feed Internals] Add current content

This internals page is used to surface debugging information useful to
developers of the NTP Interest Feed. This CL surfaces the current
Feed content, including suggestion titles, URLs and other metadata.

https://screenshot.googleplex.com/gGGcX0BZkYM

Bug: 913126
Change-Id: I48dd63698229f43bb1671a0035e7c0b6cf34559a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1506539
Commit-Queue: Natalie Chouinard <chouinard@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Reviewed-by: default avatarBrandon Wylie <wylieb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638700}
parent 168598ea
...@@ -10,6 +10,7 @@ h2 { ...@@ -10,6 +10,7 @@ h2 {
} }
table { table {
table-layout: fixed;
width: 100%; width: 100%;
} }
...@@ -19,9 +20,14 @@ table > tbody > tr:nth-child(odd) { ...@@ -19,9 +20,14 @@ table > tbody > tr:nth-child(odd) {
table td { table td {
width: 50%; width: 50%;
word-wrap: break-word;
} }
button { button {
display: block; display: block;
min-height: 30px; min-height: 30px;
} }
#current-content table td:first-child {
width: 15%;
}
...@@ -23,6 +23,7 @@ found in the LICENSE file. ...@@ -23,6 +23,7 @@ found in the LICENSE file.
</head> </head>
<body> <body>
<h2>Properties</h2> <h2>Properties</h2>
<table> <table>
<tr> <tr>
...@@ -30,6 +31,7 @@ found in the LICENSE file. ...@@ -30,6 +31,7 @@ found in the LICENSE file.
<td id="is-feed-enabled"></td> <td id="is-feed-enabled"></td>
</tr> </tr>
</table> </table>
<h2>User Classifier</h2> <h2>User Classifier</h2>
<table> <table>
<tr> <tr>
...@@ -52,6 +54,7 @@ found in the LICENSE file. ...@@ -52,6 +54,7 @@ found in the LICENSE file.
<button id="clear-cached-data"> <button id="clear-cached-data">
Clear Cache & Refresh Feed Clear Cache & Refresh Feed
</button> </button>
<h2>Last Fetch</h2> <h2>Last Fetch</h2>
<table> <table>
<tr> <tr>
...@@ -67,5 +70,33 @@ found in the LICENSE file. ...@@ -67,5 +70,33 @@ found in the LICENSE file.
<td id="refresh-suppress-time"></td> <td id="refresh-suppress-time"></td>
</tr> </tr>
</table> </table>
<h2>Current Content</h2>
<div id="current-content">
<template id="suggestion-template">
<details>
<summary class="title"></summary>
<table>
<tr>
<td>Publisher Name</td>
<td class="publisher"></td>
</tr>
<tr>
<td>URL</td>
<td><a class="url"></a></td>
</tr>
<tr>
<td>Favicon URL</td>
<td><a class="favicon"></a></td>
</tr>
<tr>
<td>Image URL</td>
<td><a class="image"></a></td>
</tr>
</table>
</details>
</template>
</div>
</body> </body>
</html> </html>
...@@ -50,6 +50,48 @@ function updatePageWithLastFetchProperties() { ...@@ -50,6 +50,48 @@ function updatePageWithLastFetchProperties() {
}); });
} }
/**
* Get and display last known content.
*/
function updatePageWithCurrentContent() {
pageHandler.getCurrentContent().then(response => {
const before = $('current-content');
const after = before.cloneNode(false);
/** @type {!Array<feedInternals.mojom.Suggestion>} */
const suggestions = response.suggestions;
for (const suggestion of suggestions) {
// Create new content item from template.
const item = document.importNode($('suggestion-template').content, true);
// Populate template with text metadata.
item.querySelector('.title').textContent = suggestion.title;
item.querySelector('.publisher').textContent = suggestion.publisherName;
// Populate template with link metadata.
setLinkNode(item.querySelector('a.url'), suggestion.url);
setLinkNode(item.querySelector('a.image'), suggestion.imageUrl);
setLinkNode(item.querySelector('a.favicon'), suggestion.faviconUrl);
after.appendChild(item);
}
before.replaceWith(after);
});
}
/**
* Populate <a> node with hyperlinked URL.
*
* @param {Element} node
* @param {string} url
*/
function setLinkNode(node, url) {
node.textContent = url;
node.href = url;
}
/** /**
* Convert time to string for display. * Convert time to string for display.
* *
...@@ -78,6 +120,7 @@ function setupEventListeners() { ...@@ -78,6 +120,7 @@ function setupEventListeners() {
// consider adding backend->frontend mojo communication to listen for // consider adding backend->frontend mojo communication to listen for
// updates, rather than waiting an arbitrary period of time. // updates, rather than waiting an arbitrary period of time.
setTimeout(updatePageWithLastFetchProperties, 1000); setTimeout(updatePageWithLastFetchProperties, 1000);
setTimeout(updatePageWithCurrentContent, 1000);
}); });
} }
...@@ -88,6 +131,7 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -88,6 +131,7 @@ document.addEventListener('DOMContentLoaded', function() {
updatePageWithProperties(); updatePageWithProperties();
updatePageWithUserClass(); updatePageWithUserClass();
updatePageWithLastFetchProperties(); updatePageWithLastFetchProperties();
updatePageWithCurrentContent();
setupEventListeners(); setupEventListeners();
}); });
......
...@@ -35,6 +35,24 @@ struct LastFetchProperties { ...@@ -35,6 +35,24 @@ struct LastFetchProperties {
Time? refresh_suppress_time; Time? refresh_suppress_time;
}; };
// Models a single suggestion in the Feed.
struct Suggestion {
// Title of the suggestion.
string title;
// URL of the suggested page.
string url;
// Name of the content's publisher.
string publisher_name;
// URL of the image associated with the suggestion.
string image_url;
// URL of the suggested page's favicon.
string favicon_url;
};
// Time wrapper to allow for nullable objects. // Time wrapper to allow for nullable objects.
struct Time { struct Time {
double ms_since_epoch; double ms_since_epoch;
...@@ -58,4 +76,7 @@ interface PageHandler { ...@@ -58,4 +76,7 @@ interface PageHandler {
// Clear all data cached by the Feed library. Also triggers a refresh of the // Clear all data cached by the Feed library. Also triggers a refresh of the
// Feed. // Feed.
ClearCachedDataAndRefreshFeed(); ClearCachedDataAndRefreshFeed();
// Get the last known content with metadata.
GetCurrentContent() => (array<Suggestion> suggestions);
}; };
...@@ -10,10 +10,12 @@ ...@@ -10,10 +10,12 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/android/feed/feed_lifecycle_bridge.h" #include "chrome/browser/android/feed/feed_lifecycle_bridge.h"
#include "components/feed/content/feed_host_service.h" #include "components/feed/content/feed_host_service.h"
#include "components/feed/content/feed_offline_host.h"
#include "components/feed/core/feed_scheduler_host.h" #include "components/feed/core/feed_scheduler_host.h"
#include "components/feed/core/pref_names.h" #include "components/feed/core/pref_names.h"
#include "components/feed/core/user_classifier.h" #include "components/feed/core/user_classifier.h"
#include "components/feed/feed_feature_list.h" #include "components/feed/feed_feature_list.h"
#include "components/offline_pages/core/prefetch/suggestions_provider.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
namespace { namespace {
...@@ -31,7 +33,9 @@ FeedInternalsPageHandler::FeedInternalsPageHandler( ...@@ -31,7 +33,9 @@ FeedInternalsPageHandler::FeedInternalsPageHandler(
PrefService* pref_service) PrefService* pref_service)
: binding_(this, std::move(request)), : binding_(this, std::move(request)),
feed_scheduler_host_(feed_host_service->GetSchedulerHost()), feed_scheduler_host_(feed_host_service->GetSchedulerHost()),
pref_service_(pref_service) {} feed_offline_host_(feed_host_service->GetOfflineHost()),
pref_service_(pref_service),
weak_ptr_factory_(this) {}
FeedInternalsPageHandler::~FeedInternalsPageHandler() = default; FeedInternalsPageHandler::~FeedInternalsPageHandler() = default;
...@@ -84,3 +88,29 @@ void FeedInternalsPageHandler::ClearUserClassifierProperties() { ...@@ -84,3 +88,29 @@ void FeedInternalsPageHandler::ClearUserClassifierProperties() {
void FeedInternalsPageHandler::ClearCachedDataAndRefreshFeed() { void FeedInternalsPageHandler::ClearCachedDataAndRefreshFeed() {
feed::FeedLifecycleBridge::ClearCachedData(); feed::FeedLifecycleBridge::ClearCachedData();
} }
void FeedInternalsPageHandler::GetCurrentContent(
GetCurrentContentCallback callback) {
feed_offline_host_->GetCurrentArticleSuggestions(base::BindOnce(
&FeedInternalsPageHandler::OnGetCurrentArticleSuggestionsDone,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void FeedInternalsPageHandler::OnGetCurrentArticleSuggestionsDone(
GetCurrentContentCallback callback,
std::vector<offline_pages::PrefetchSuggestion> results) {
std::vector<feed_internals::mojom::SuggestionPtr> suggestions;
for (offline_pages::PrefetchSuggestion result : results) {
auto suggestion = feed_internals::mojom::Suggestion::New();
suggestion->title = std::move(result.article_title);
suggestion->url = result.article_url.spec();
suggestion->publisher_name = std::move(result.article_attribution);
suggestion->image_url = result.thumbnail_url.spec();
suggestion->favicon_url = result.favicon_url.spec();
suggestions.push_back(std::move(suggestion));
}
std::move(callback).Run(std::move(suggestions));
}
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_ #ifndef CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h" #include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
...@@ -13,9 +16,14 @@ class PrefService; ...@@ -13,9 +16,14 @@ class PrefService;
namespace feed { namespace feed {
class FeedHostService; class FeedHostService;
class FeedOfflineHost;
class FeedSchedulerHost; class FeedSchedulerHost;
} // namespace feed } // namespace feed
namespace offline_pages {
struct PrefetchSuggestion;
} // namespace offline_pages
// Concrete implementation of feed_internals::mojom::PageHandler. // Concrete implementation of feed_internals::mojom::PageHandler.
class FeedInternalsPageHandler : public feed_internals::mojom::PageHandler { class FeedInternalsPageHandler : public feed_internals::mojom::PageHandler {
public: public:
...@@ -31,15 +39,23 @@ class FeedInternalsPageHandler : public feed_internals::mojom::PageHandler { ...@@ -31,15 +39,23 @@ class FeedInternalsPageHandler : public feed_internals::mojom::PageHandler {
void ClearUserClassifierProperties() override; void ClearUserClassifierProperties() override;
void GetLastFetchProperties(GetLastFetchPropertiesCallback) override; void GetLastFetchProperties(GetLastFetchPropertiesCallback) override;
void ClearCachedDataAndRefreshFeed() override; void ClearCachedDataAndRefreshFeed() override;
void GetCurrentContent(GetCurrentContentCallback) override;
private: private:
// Binding from the mojo interface to concrete implementation. // Binding from the mojo interface to concrete implementation.
mojo::Binding<feed_internals::mojom::PageHandler> binding_; mojo::Binding<feed_internals::mojom::PageHandler> binding_;
void OnGetCurrentArticleSuggestionsDone(
GetCurrentContentCallback callback,
std::vector<offline_pages::PrefetchSuggestion> suggestions);
// Services that provide the data and functionality. // Services that provide the data and functionality.
feed::FeedSchedulerHost* feed_scheduler_host_; feed::FeedSchedulerHost* feed_scheduler_host_;
feed::FeedOfflineHost* feed_offline_host_;
PrefService* pref_service_; PrefService* pref_service_;
base::WeakPtrFactory<FeedInternalsPageHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FeedInternalsPageHandler); DISALLOW_COPY_AND_ASSIGN(FeedInternalsPageHandler);
}; };
......
...@@ -226,7 +226,7 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer { ...@@ -226,7 +226,7 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer {
throttlers_; throttlers_;
// Status of the last fetch for debugging. // Status of the last fetch for debugging.
int last_fetch_status_; int last_fetch_status_ = 0;
DISALLOW_COPY_AND_ASSIGN(FeedSchedulerHost); DISALLOW_COPY_AND_ASSIGN(FeedSchedulerHost);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment