Commit 0c3ea42d authored by Trent Begin's avatar Trent Begin Committed by Commit Bot

network-health: add 'Send Feedback Report' button

This change adds a button to the chrome://network to send a feedback
report populated with the results of the Network diagnostic tests.

content

Bug: chromium:1098405
Test: Click Send Feedback Report button and inspect EXTRA_DIAGNOSTICS
Change-Id: I3707d62878bd49a80ecf76ec235619a6662b34dd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2334000
Commit-Queue: Trent Begin <tbegin@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795658}
parent 46a3e2bb
......@@ -3630,6 +3630,9 @@
<message name="IDS_NETWORK_DIAGNOSTICS_RUN_ALL" desc="Label for Network diagnostics run all routines button">
Run All Routines
</message>
<message name="IDS_NETWORK_DIAGNOSTICS_SEND_FEEDBACK" desc="Label for Network diagnostics send feedback report button">
Send Feedback Report
</message>
<!-- Set time/date UI display strings -->
......
784617f08abdb0d262c102720d0a63f443d1ddb3
\ No newline at end of file
......@@ -43,6 +43,7 @@ constexpr webui::LocalizedString kLocalizedStrings[] = {
{"NetworkDiagnosticsNotRun", IDS_NETWORK_DIAGNOSTICS_NOT_RUN},
{"NetworkDiagnosticsRun", IDS_NETWORK_DIAGNOSTICS_RUN},
{"NetworkDiagnosticsRunAll", IDS_NETWORK_DIAGNOSTICS_RUN_ALL},
{"NetworkDiagnosticsSendFeedback", IDS_NETWORK_DIAGNOSTICS_SEND_FEEDBACK},
};
} // namespace
......
......@@ -88,7 +88,9 @@
<h2>$i18n{networkHealthLabel}</h2>
<network-health-summary></network-health-summary>
<h2>$i18n{networkDiagnosticsLabel}</h2>
<network-diagnostics></network-diagnostics>
<network-diagnostics
on-open-feedback-dialog="onOpenFeedbackDialog_">
</network-diagnostics>
</div>
<div class="tabpanel" id="logs">
......
......@@ -180,6 +180,16 @@ Polymer({
});
},
/**
* Handles requests to open the feedback report dialog. The provided string
* in the event will be sent as a part of the feedback report.
* @param {!Event<string>} event
* @private
*/
onOpenFeedbackDialog_(event) {
chrome.send('OpenFeedbackDialog', [event.detail]);
},
/**
* @param {!Event<!{detail:{customData: string}}>} event
* @private
......
......@@ -63,6 +63,7 @@ enum FeedbackSource {
kFeedbackSourceMediaApp,
kFeedbackSourceHelpApp,
kFeedbackSourceKaleidoscope,
kFeedbackSourceNetworkHealthPage,
// Must be last.
kFeedbackSourceCount,
......
......@@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/net/network_health/network_health_localized_strings.h"
#include "chrome/browser/chromeos/net/network_health/network_health_service.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h"
#include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h"
#include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h"
......@@ -315,6 +316,29 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler {
DISALLOW_COPY_AND_ASSIGN(NetworkConfigMessageHandler);
};
class NetworkDiagnosticsMessageHandler : public content::WebUIMessageHandler {
public:
NetworkDiagnosticsMessageHandler() = default;
~NetworkDiagnosticsMessageHandler() override = default;
void RegisterMessages() override {
web_ui()->RegisterMessageCallback(
"OpenFeedbackDialog",
base::BindRepeating(
&NetworkDiagnosticsMessageHandler::OpenFeedbackDialog,
base::Unretained(this)));
}
private:
void OpenFeedbackDialog(const base::ListValue* value) {
const std::string result = value->GetList()[0].GetString();
chrome::ShowFeedbackPage(nullptr, chrome::kFeedbackSourceNetworkHealthPage,
"" /*description_template*/,
"" /*description_template_placeholder*/,
"network-health", result);
}
};
} // namespace
// static
......@@ -458,6 +482,8 @@ NetworkUI::NetworkUI(content::WebUI* web_ui)
web_ui->AddMessageHandler(std::make_unique<NetworkConfigMessageHandler>());
web_ui->AddMessageHandler(std::make_unique<OncImportMessageHandler>());
web_ui->AddMessageHandler(std::make_unique<NetworkLogsMessageHandler>());
web_ui->AddMessageHandler(
std::make_unique<NetworkDiagnosticsMessageHandler>());
// Enable extension API calls in the WebUI.
extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents());
......
......@@ -56,6 +56,7 @@ js_library("network_health_summary.m") {
js_library("network_diagnostics.m") {
sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.m.js" ]
deps = [
"//chromeos/services/network_health/public/mojom:mojom_js_library_for_compile",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:i18n_behavior.m",
]
......
......@@ -9,6 +9,10 @@
<dom-module id="network-diagnostics">
<template>
<style>
.button-group > * {
margin-inline-start: 10px;
}
.routine-group {
display: inline-flex;
flex-wrap: wrap;
......@@ -51,10 +55,13 @@
background-color: rgb(255, 242, 204);
}
</style>
<div>
<cr-button class="action-button" on-click="onRunAllRoutinesClick_">
<div class="button-group">
<cr-button on-click="onRunAllRoutinesClick_">
[[i18n('NetworkDiagnosticsRunAll')]]
</cr-button>
<cr-button on-click="onSendFeedbackReportClick_">
[[i18n('NetworkDiagnosticsSendFeedback')]]
</cr-button>
</div>
<div class="routine-group">
<template is="dom-repeat" items="[[routines_]]" as="routine">
......
......@@ -7,6 +7,20 @@
* @fileoverview Polymer element for interacting with Network Diagnostics.
*/
// Namespace to make using the mojom objects more readable.
const diagnosticsMojom = chromeos.networkDiagnostics.mojom;
/**
* A routine response from the Network Diagnostics mojo service.
* @typedef {{
* verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict,
* }}
* RoutineResponse can optionally have a `problems` field, which is an array of
* enums relevant to the routine run. Unfortunately the closure compiler cannot
* handle optional object fields.
*/
let RoutineResponse;
/**
* A network diagnostics routine. Holds descriptive information about the
* routine, and it's transient state.
......@@ -15,18 +29,11 @@
* type: !RoutineType,
* running: boolean,
* resultMsg: string,
* result: ?RoutineResponse,
* }}
*/
let Routine;
/**
* A routine response from the Network Diagnostics mojo service.
* @typedef {{
* verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict
* }}
*/
let RoutineResponse;
/**
* Definition for all Network diagnostic routine types. This enum is intended
* to be used as an index in an array of routines.
......@@ -49,7 +56,7 @@ const RoutineType = {
* @return {!Routine} Routine object
*/
function createRoutine(name, type) {
return {name: name, type: type, running: false, resultMsg: ''};
return {name: name, type: type, running: false, resultMsg: '', result: null};
}
Polymer({
......@@ -97,8 +104,8 @@ Polymer({
/** @override */
created() {
this.networkDiagnostics_ = chromeos.networkDiagnostics.mojom
.NetworkDiagnosticsRoutines.getRemote();
this.networkDiagnostics_ =
diagnosticsMojom.NetworkDiagnosticsRoutines.getRemote();
},
/** @private */
......@@ -116,6 +123,26 @@ Polymer({
this.runRoutine_(event.model.index);
},
/** @private */
onSendFeedbackReportClick_() {
const results = {};
for (const routine of this.routines_) {
if (routine.result) {
const name = routine.name.replace('NetworkDiagnostics', '');
const result = {};
result['verdict'] =
this.getRoutineVerdictFeedbackString_(routine.result.verdict);
if (routine.result.problems && routine.result.problems.length > 0) {
result['problems'] = this.getRoutineProblemsFeedbackString_(
routine.type, routine.result.problems);
}
results[name] = result;
}
}
this.fire('open-feedback-dialog', JSON.stringify(results, undefined, 2));
},
/**
* @param {!RoutineType} type
* @private
......@@ -123,6 +150,7 @@ Polymer({
runRoutine_(type) {
this.set(`routines_.${type}.running`, true);
this.set(`routines_.${type}.resultMsg`, '');
this.set(`routines_.${type}.result`, null);
const element =
this.shadowRoot.querySelectorAll('.routine-container')[type];
element.classList.remove('result-passed', 'result-error', 'result-not-run');
......@@ -172,20 +200,149 @@ Polymer({
let resultMsg = '';
switch (result.verdict) {
case chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem:
case diagnosticsMojom.RoutineVerdict.kNoProblem:
resultMsg = this.i18n('NetworkDiagnosticsPassed');
element.classList.add('result-passed');
break;
case chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem:
case diagnosticsMojom.RoutineVerdict.kProblem:
resultMsg = this.i18n('NetworkDiagnosticsFailed');
element.classList.add('result-error');
break;
case chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun:
case diagnosticsMojom.RoutineVerdict.kNotRun:
resultMsg = this.i18n('NetworkDiagnosticsNotRun');
element.classList.add('result-not-run');
break;
}
this.set(routine + '.result', result);
this.set(routine + '.resultMsg', resultMsg);
},
/**
*
* @param {!RoutineType} type The type of routine
* @param {!Array<number>} problems The list of problems for the routine
* @return {Array<string>} String for a networking problem used for feedback
* @private
*/
getRoutineProblemsFeedbackString_(type, problems) {
const problemStrings = [];
for (const problem of problems) {
switch (type) {
case RoutineType.SIGNAL_STRENGTH:
switch (problem) {
case diagnosticsMojom.SignalStrengthProblem.kSignalNotFound:
problemStrings.push('Signal Not Found');
break;
case diagnosticsMojom.SignalStrengthProblem.kWeakSignal:
problemStrings.push('Weak Signal');
break;
}
break;
case RoutineType.GATEWAY_PING:
switch (problem) {
case diagnosticsMojom.GatewayCanBePingedProblem.kUnreachableGateway:
problemStrings.push('Gateway is Unreachable');
break;
case diagnosticsMojom.GatewayCanBePingedProblem
.kFailedToPingDefaultNetwork:
problemStrings.push('Failed to ping default network');
break;
case diagnosticsMojom.GatewayCanBePingedProblem
.kDefaultNetworkAboveLatencyThreshold:
problemStrings.push('Default network above latency threshold');
break;
case diagnosticsMojom.GatewayCanBePingedProblem
.kUnsuccessfulNonDefaultNetworksPings:
problemStrings.push('Non-default network has failed pings');
break;
case diagnosticsMojom.GatewayCanBePingedProblem
.kNonDefaultNetworksAboveLatencyThreshold:
problemStrings.push(
'Non-default network is above latency threshold');
break;
}
break;
case RoutineType.SECURE_WIFI:
switch (problem) {
case diagnosticsMojom.HasSecureWiFiConnectionProblem
.kSecurityTypeNone:
problemStrings.push('WiFi Network is not secure');
break;
case diagnosticsMojom.HasSecureWiFiConnectionProblem
.kSecurityTypeWep8021x:
problemStrings.push('WiFi Network secured with WEP 802.1x');
break;
case diagnosticsMojom.HasSecureWiFiConnectionProblem
.kSecurityTypeWepPsk:
problemStrings.push('WiFi Network secured with WEP PSK');
break;
case diagnosticsMojom.HasSecureWiFiConnectionProblem
.kUnknownSecurityType:
problemStrings.push('WiFi Network secured with WEP PSK');
break;
}
break;
case RoutineType.DNS_RESOLVER:
switch (problem) {
case diagnosticsMojom.DnsResolverPresentProblem.kNoNameServersFound:
problemStrings.push('No name servers found');
break;
case diagnosticsMojom.DnsResolverPresentProblem
.kMalformedNameServers:
problemStrings.push('Malformed name servers');
break;
case diagnosticsMojom.DnsResolverPresentProblem.kEmptyNameServers:
problemStrings.push('Empty name servers');
break;
}
break;
case RoutineType.DNS_LATENCY:
switch (problem) {
case diagnosticsMojom.DnsLatencyProblem.kFailedToResolveAllHosts:
problemStrings.push('Failed to resolve all hosts');
break;
case diagnosticsMojom.DnsLatencyProblem.kSlightlyAboveThreshold:
problemStrings.push('DNS latency slightly above threshold');
break;
case diagnosticsMojom.DnsLatencyProblem
.kSignificantlyAboveThreshold:
problemStrings.push('DNS latency significantly above threshold');
break;
}
break;
case RoutineType.DNS_RESOLUTION:
switch (problem) {
case diagnosticsMojom.DnsResolutionProblem.kFailedToResolveHost:
problemStrings.push('Failed to resolve host');
break;
}
break;
}
}
return problemStrings;
},
/**
* @param {!chromeos.networkDiagnostics.mojom.RoutineVerdict} verdict
* @return {string} String for a network diagnostic verdict used for feedback
* @private
*/
getRoutineVerdictFeedbackString_(verdict) {
switch (verdict) {
case diagnosticsMojom.RoutineVerdict.kNoProblem:
return 'Passed';
case diagnosticsMojom.RoutineVerdict.kNotRun:
return 'Not Run';
case diagnosticsMojom.RoutineVerdict.kProblem:
return 'Failed';
}
return 'Unknown';
},
});
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