Commit 135a225a authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

[EOC] Backend implementation for chrome://eoc-internals

Implementing backend logic for the eoc-internals page. Adding methods
required to expose the reporter/cache to the debugging backend.

Bug: 830932
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Ib83c824661e240685507105f800ae821fd706c85
Reviewed-on: https://chromium-review.googlesource.com/1081488
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Reviewed-by: default avatarPatrick Noland <pnoland@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565755}
parent 5e09a6b7
......@@ -4,5 +4,96 @@
module eoc_internals.mojom;
// Distillation of results from a server request for page suggestions.
struct SuggestionResult {
// The URL of the page that the suggestions are for.
string url;
// The conditions under which the peek was displayed.
PeekConditions peek_conditions;
// The suggestions for the page.
array<Suggestion> suggestions;
};
// Tracks the server-defined parameters for when to show the peek bar.
struct PeekConditions {
// A measure of confidence that auto-peek should be enabled for this response
// in the range [0, 1].
float confidence;
// The percentage of the page that the user scrolls required for an auto
// peek to occur.
float page_scroll_percentage;
// The minimum time (seconds) the user spends on the page required for
// auto peek.
float minimum_seconds_on_page;
// The maximum number of auto peeks that we can show for this page.
int64 maximum_number_of_peeks;
};
// Models a single suggestion.
struct Suggestion {
// The URL for the suggestion.
string url;
// Title displayed in the suggestion sheet.
string title;
// Name of the publisher.
string publisher_name;
// Text snippet displayed on the sheet.
string snippet;
// The ID of the image displayed for this suggestion.
string image_id;
// The ID of the favicon for the suggested URL.
string favicon_image_id;
};
// Metrics event that was constructed for a page.
struct MetricEvent {
// The URL which the metrics event is for.
string url;
// Did the sheet peek show.
bool sheet_peeked;
// If the peek was closed without being opened.
bool sheet_opened;
// If the sheet was opened from the peek.
bool sheet_closed;
// If any suggestion was clicked on from the sheet.
bool any_suggestion_taken;
// If any suggestion was downloaded from the sheet.
bool any_suggestion_downloaded;
};
// Browser interface for the page. Consists of calls for data and hooks for
// interactivity.
interface PageHandler {
};
\ No newline at end of file
// Get a key/value mapping of properties.
GetProperties() => (map<string, string> properties);
// Change the triggering time to the given duration.
SetTriggerTime(int64 seconds);
// Get cached metrics.
GetCachedMetricEvents() => (array<MetricEvent> metrics);
// Clear the cached metrics.
ClearCachedMetricEvents() => ();
// Get the cached suggestion results.
GetCachedSuggestionResults() => (array<SuggestionResult> results);
// Clear the cached suggestions.
ClearCachedSuggestionResults() => ();
};
// 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 "chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h"
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "chrome/browser/android/chrome_feature_list.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_cache.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_features.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_fetch.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_result.h"
using contextual_suggestions::ContextualContentSuggestionsService;
using contextual_suggestions::ContextualSuggestionsCache;
using contextual_suggestions::ContextualSuggestionsDebuggingReporter;
using contextual_suggestions::ContextualSuggestionsFetch;
using contextual_suggestions::ContextualSuggestionsResult;
namespace {
std::string GetAreChromeFlagsSetupString() {
return base::FeatureList::IsEnabled(
contextual_suggestions::kContextualSuggestionsBottomSheet) &&
base::FeatureList::IsEnabled(
chrome::android::kChromeModernDesign)
? "true"
: "false";
}
} // namespace
EocInternalsPageHandler::EocInternalsPageHandler(
eoc_internals::mojom::PageHandlerRequest request)
: binding_(this, std::move(request)) {}
eoc_internals::mojom::PageHandlerRequest request,
ContextualContentSuggestionsService* contextual_content_suggestions_service)
: binding_(this, std::move(request)),
contextual_content_suggestions_service_(
contextual_content_suggestions_service) {}
EocInternalsPageHandler::~EocInternalsPageHandler() {}
void EocInternalsPageHandler::GetProperties(GetPropertiesCallback callback) {
base::flat_map<std::string, std::string> properties;
// TODO(wylieb): Find the actual time when it's moved to c++ and configurable,
// see b/838748 for more details.
// TODO(wylieb): Instead of having a map<string, string>, move this to a mojo
// struct and populate the fields to html in javascript.
properties["time-to-trigger"] = "2";
properties["chrome-flags-setup"] = GetAreChromeFlagsSetupString();
properties["fetch-endpoint-url"] =
ContextualSuggestionsFetch::GetFetchEndpoint();
std::move(callback).Run(properties);
}
void EocInternalsPageHandler::SetTriggerTime(int64_t seconds) {
// TODO(wylieb): Implement this when updating triggering time manually is
// supported.
}
void EocInternalsPageHandler::GetCachedMetricEvents(
GetCachedMetricEventsCallback callback) {
std::vector<eoc_internals::mojom::MetricEventPtr> metric_events;
if (contextual_content_suggestions_service_ == nullptr) {
std::move(callback).Run(std::move(metric_events));
return;
}
ContextualSuggestionsDebuggingReporter* debugging_reporter =
contextual_content_suggestions_service_->GetDebuggingReporter();
// Events will be ordered from oldest -> newest.
// TODO(wylieb): Consider storing a timestamp along with metric events so that
// clear ordering and sorting can be used.
for (auto debug_event : debugging_reporter->GetEvents()) {
auto metric_event = eoc_internals::mojom::MetricEvent::New();
metric_event->url = debug_event.url;
metric_event->sheet_peeked = debug_event.sheet_peeked;
metric_event->sheet_opened = debug_event.sheet_opened;
metric_event->sheet_closed = debug_event.sheet_closed;
metric_event->any_suggestion_taken = debug_event.any_suggestion_taken;
metric_event->any_suggestion_downloaded =
debug_event.any_suggestion_downloaded;
metric_events.push_back(std::move(metric_event));
}
std::move(callback).Run(std::move(metric_events));
}
void EocInternalsPageHandler::ClearCachedMetricEvents(
ClearCachedMetricEventsCallback callback) {
contextual_content_suggestions_service_->GetDebuggingReporter()
->ClearEvents();
std::move(callback).Run();
}
void EocInternalsPageHandler::GetCachedSuggestionResults(
GetCachedSuggestionResultsCallback callback) {
std::vector<eoc_internals::mojom::SuggestionResultPtr> suggestion_results;
if (contextual_content_suggestions_service_ == nullptr) {
std::move(callback).Run(std::move(suggestion_results));
return;
}
base::flat_map<GURL, ContextualSuggestionsResult> result_map =
contextual_content_suggestions_service_
->GetAllCachedResultsForDebugging();
for (auto iter = result_map.begin(); iter != result_map.end(); iter++) {
auto suggestion_result = eoc_internals::mojom::SuggestionResult::New();
suggestion_result->url = iter->first.spec();
auto peek_conditions = eoc_internals::mojom::PeekConditions::New();
peek_conditions->confidence = iter->second.peek_conditions.confidence;
peek_conditions->page_scroll_percentage =
iter->second.peek_conditions.page_scroll_percentage;
peek_conditions->minimum_seconds_on_page =
iter->second.peek_conditions.minimum_seconds_on_page;
peek_conditions->maximum_number_of_peeks =
iter->second.peek_conditions.maximum_number_of_peeks;
suggestion_result->peek_conditions = std::move(peek_conditions);
for (const auto& cluster : iter->second.clusters) {
for (const auto& contextual_suggestion : cluster.suggestions) {
auto suggestion = eoc_internals::mojom::Suggestion::New();
suggestion->url = contextual_suggestion.url.spec();
suggestion->title = contextual_suggestion.title;
suggestion->publisher_name = contextual_suggestion.publisher_name;
suggestion->snippet = contextual_suggestion.snippet;
suggestion->image_id = contextual_suggestion.image_id;
suggestion->favicon_image_id = contextual_suggestion.favicon_image_id;
suggestion_result->suggestions.push_back(std::move(suggestion));
}
}
suggestion_results.push_back(std::move(suggestion_result));
}
std::move(callback).Run(std::move(suggestion_results));
}
void EocInternalsPageHandler::ClearCachedSuggestionResults(
ClearCachedSuggestionResultsCallback callback) {
contextual_content_suggestions_service_->ClearCachedResultsForDebugging();
std::move(callback).Run();
}
......@@ -7,17 +7,31 @@
#include "base/macros.h"
#include "chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom.h"
#include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h"
#include "mojo/public/cpp/bindings/binding.h"
// Concrete implementation of eoc_internals::mojom::PageHandler.
class EocInternalsPageHandler : public eoc_internals::mojom::PageHandler {
public:
explicit EocInternalsPageHandler(
eoc_internals::mojom::PageHandlerRequest request);
EocInternalsPageHandler(
eoc_internals::mojom::PageHandlerRequest request,
contextual_suggestions::ContextualContentSuggestionsService*
contextual_content_suggestions_service);
~EocInternalsPageHandler() override;
private:
// eoc_internals::mojom::EocInternalsPageHandler
void GetProperties(GetPropertiesCallback) override;
void SetTriggerTime(int64_t seconds) override;
void GetCachedMetricEvents(GetCachedMetricEventsCallback) override;
void ClearCachedMetricEvents(ClearCachedMetricEventsCallback) override;
void GetCachedSuggestionResults(GetCachedSuggestionResultsCallback) override;
void ClearCachedSuggestionResults(
ClearCachedSuggestionResultsCallback) override;
mojo::Binding<eoc_internals::mojom::PageHandler> binding_;
contextual_suggestions::ContextualContentSuggestionsService*
contextual_content_suggestions_service_;
DISALLOW_COPY_AND_ASSIGN(EocInternalsPageHandler);
};
......
......@@ -5,6 +5,7 @@
#include "chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h"
#include "build/build_config.h"
#include "chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h"
#include "chrome/common/url_constants.h"
......@@ -15,6 +16,8 @@
#include "chrome/browser/android/chrome_feature_list.h"
#endif
using contextual_suggestions::ContextualContentSuggestionsService;
EocInternalsUI::EocInternalsUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui) {
content::WebUIDataSource* source =
......@@ -27,6 +30,8 @@ EocInternalsUI::EocInternalsUI(content::WebUI* web_ui)
source->UseGzip();
Profile* profile = Profile::FromWebUI(web_ui);
contextual_content_suggestions_service_ =
ContextualContentSuggestionsServiceFactory::GetForProfile(profile);
content::WebUIDataSource::Add(profile, source);
// This class is the caller of the callback when an observer interface is
// triggered. So this base::Unretained is safe.
......@@ -38,5 +43,6 @@ EocInternalsUI::~EocInternalsUI() {}
void EocInternalsUI::BindEocInternalsPageHandler(
eoc_internals::mojom::PageHandlerRequest request) {
page_handler_.reset(new EocInternalsPageHandler(std::move(request)));
page_handler_.reset(new EocInternalsPageHandler(
std::move(request), contextual_content_suggestions_service_));
}
......@@ -25,6 +25,8 @@ class EocInternalsUI : public ui::MojoWebUIController {
eoc_internals::mojom::PageHandlerRequest request);
std::unique_ptr<EocInternalsPageHandler> page_handler_;
contextual_suggestions::ContextualContentSuggestionsService*
contextual_content_suggestions_service_;
DISALLOW_COPY_AND_ASSIGN(EocInternalsUI);
};
......
......@@ -99,6 +99,20 @@ void ContextualContentSuggestionsService::FetchDone(
std::move(callback).Run(result);
}
ContextualSuggestionsDebuggingReporter*
ContextualContentSuggestionsService::GetDebuggingReporter() {
return reporter_provider_->GetDebuggingReporter();
}
base::flat_map<GURL, ContextualSuggestionsResult>
ContextualContentSuggestionsService::GetAllCachedResultsForDebugging() {
return fetch_cache_.GetAllCachedResultsForDebugging();
}
void ContextualContentSuggestionsService::ClearCachedResultsForDebugging() {
fetch_cache_.Clear();
}
std::unique_ptr<
contextual_suggestions::ContextualContentSuggestionsServiceProxy>
ContextualContentSuggestionsService::CreateProxy() {
......
......@@ -17,6 +17,7 @@
#include "components/ntp_snippets/callbacks.h"
#include "components/ntp_snippets/content_suggestion.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_cache.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_reporter.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
......@@ -65,6 +66,16 @@ class ContextualContentSuggestionsService : public KeyedService {
ReportFetchMetricsCallback metrics_callback,
ContextualSuggestionsResult result);
// Used to surface metrics events via chrome://eoc-internals.
ContextualSuggestionsDebuggingReporter* GetDebuggingReporter();
// Expose cached results for debugging.
base::flat_map<GURL, ContextualSuggestionsResult>
GetAllCachedResultsForDebugging();
// Clear the cached results for debugging.
void ClearCachedResultsForDebugging();
std::unique_ptr<ContextualContentSuggestionsServiceProxy> CreateProxy();
private:
......
......@@ -10,6 +10,12 @@ ContextualSuggestionsCache::ContextualSuggestionsCache(size_t capacity)
: cache_(capacity) {}
ContextualSuggestionsCache::~ContextualSuggestionsCache() = default;
base::flat_map<GURL, ContextualSuggestionsResult>
ContextualSuggestionsCache::GetAllCachedResultsForDebugging() {
return base::flat_map<GURL, ContextualSuggestionsResult>(cache_.begin(),
cache_.end());
}
bool ContextualSuggestionsCache::GetSuggestionsResult(
const GURL& url,
ContextualSuggestionsResult* result) {
......
......@@ -5,6 +5,7 @@
#ifndef COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTIONS_CACHE_H_
#define COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTIONS_CACHE_H_
#include "base/containers/flat_map.h"
#include "base/containers/mru_cache.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_result.h"
#include "url/gurl.h"
......@@ -30,6 +31,10 @@ class ContextualSuggestionsCache {
// Removes all items from the cache.
void Clear();
// Returns all suggestion results for debugging purposes.
base::flat_map<GURL, ContextualSuggestionsResult>
GetAllCachedResultsForDebugging();
private:
base::MRUCache<GURL, ContextualSuggestionsResult> cache_;
};
......
......@@ -23,6 +23,10 @@ ContextualSuggestionsDebuggingReporter::GetEvents() const {
return events_;
}
void ContextualSuggestionsDebuggingReporter::ClearEvents() {
events_.clear();
}
void ContextualSuggestionsDebuggingReporter::SetupForPage(
const std::string& url,
ukm::SourceId source_id) {
......
......@@ -47,6 +47,9 @@ class ContextualSuggestionsDebuggingReporter
// Get all events currently in the buffer.
const std::vector<ContextualSuggestionsDebuggingEvent>& GetEvents() const;
// Clear the debugging cache of events.
void ClearEvents();
// ContextualSuggestionsReporter
void SetupForPage(const std::string& url, ukm::SourceId source_id) override;
void RecordEvent(
......
......@@ -28,6 +28,11 @@ ContextualSuggestionsReporterProvider::CreateReporter() {
return reporter;
}
ContextualSuggestionsDebuggingReporter*
ContextualSuggestionsReporterProvider::GetDebuggingReporter() {
return debugging_reporter_.get();
}
ContextualSuggestionsReporter::ContextualSuggestionsReporter() = default;
ContextualSuggestionsReporter::~ContextualSuggestionsReporter() = default;
......
......@@ -29,6 +29,8 @@ class ContextualSuggestionsReporterProvider {
virtual std::unique_ptr<ContextualSuggestionsReporter> CreateReporter();
virtual ContextualSuggestionsDebuggingReporter* GetDebuggingReporter();
private:
// The debugging reporter is shared between instances of top-level reporter.
// Since multiple objects need a reference to this, it's kept as a unique
......
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