Commit 682c3793 authored by Wenzhao Zang's avatar Wenzhao Zang Committed by Commit Bot

Add Bluetooth logging option for Google internal users.

This CL introduces a new checkbox that will be enabled only for users on the
google.com domain. This checkbox is only shown if we detect that the google
internal user is trying to file feedback related to bluetooth.

This CL only introduces the UI changes. Once the platforms-side changes land
to collect bluetooth logs for Google internal users, I'll send a follow on CL
that gathers those logs and attaches them to the feedback report.

R=afakhry@chromium.org

Bug: 872403
Change-Id: I937ddf8002373a861fbe5252ce37570c9f2a2f63
Reviewed-on: https://chromium-review.googlesource.com/1166594Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Commit-Queue: Wenzhao (Colin) Zang <wzang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583790}
parent 5d123b36
...@@ -5274,6 +5274,12 @@ the Bookmarks menu."> ...@@ -5274,6 +5274,12 @@ the Bookmarks menu.">
<message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system performance data on the bug report dialog box"> <message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system performance data on the bug report dialog box">
Send performance trace data Send performance trace data
</message> </message>
<message name="IDS_FEEDBACK_BLUETOOTH_LOGS_CHECKBOX" desc="Checkbox for including bluetooth logs">
Attach <ph name="BEGIN_LINK">&lt;a href="#" id="bluetooth-logs-info-link"&gt;</ph>Bluetooth Logs<ph name="END_LINK">&lt;/a&gt;</ph> (Google internal)
</message>
<message name="IDS_FEEDBACK_BLUETOOTH_LOGS_MESSAGE" desc="Message shown after user clicks on the bluetooth logs hyperlink">
To better diagnose Bluetooth issues, Googlers can include additional Bluetooth logs with their feedback reports. When this option is checked, your report will include btsnoop and HCI logs from your current session, sanitized to remove as much PII as possible. Access to these logs will be restricted to managers of the Chrome OS product group in Listnr. Logs will be purged after 90 days.
</message>
<message name="IDS_FEEDBACK_OFFLINE_DIALOG_TITLE" desc="The title of the message box displayed when the user attempts to send a report while offline"> <message name="IDS_FEEDBACK_OFFLINE_DIALOG_TITLE" desc="The title of the message box displayed when the user attempts to send a report while offline">
Feedback Report Feedback Report
</message> </message>
......
...@@ -77,6 +77,8 @@ ChromeFeedbackPrivateDelegate::GetStrings( ...@@ -77,6 +77,8 @@ ChromeFeedbackPrivateDelegate::GetStrings(
SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE); SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE);
SET_STRING("performance-trace", SET_STRING("performance-trace",
IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX); IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX);
SET_STRING("bluetooth-logs-info", IDS_FEEDBACK_BLUETOOTH_LOGS_CHECKBOX);
SET_STRING("bluetooth-logs-message", IDS_FEEDBACK_BLUETOOTH_LOGS_MESSAGE);
// Add the localized strings needed for the "system information" page. // Add the localized strings needed for the "system information" page.
SET_STRING("sysinfoPageTitle", IDS_FEEDBACK_SYSINFO_PAGE_TITLE); SET_STRING("sysinfoPageTitle", IDS_FEEDBACK_SYSINFO_PAGE_TITLE);
SET_STRING("sysinfoPageDescription", IDS_ABOUT_SYS_DESC); SET_STRING("sysinfoPageDescription", IDS_ABOUT_SYS_DESC);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <string> #include <string>
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "chrome/browser/feedback/feedback_dialog_utils.h" #include "chrome/browser/feedback/feedback_dialog_utils.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
...@@ -13,10 +14,37 @@ ...@@ -13,10 +14,37 @@
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "extensions/browser/api/feedback_private/feedback_private_api.h" #include "extensions/browser/api/feedback_private/feedback_private_api.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/signin/signin_manager_factory.h"
#include "components/signin/core/browser/signin_manager.h"
#endif
namespace feedback_private = extensions::api::feedback_private; namespace feedback_private = extensions::api::feedback_private;
namespace chrome { namespace chrome {
namespace {
#if defined(OS_CHROMEOS)
constexpr char kGoogleDotCom[] = "@google.com";
// Returns if the feedback page is considered to be triggered from user
// interaction.
bool IsFromUserInteraction(FeedbackSource source) {
switch (source) {
case kFeedbackSourceArcApp:
case kFeedbackSourceAsh:
case kFeedbackSourceBrowserCommand:
case kFeedbackSourceMdSettingsAboutPage:
case kFeedbackSourceOldSettingsAboutPage:
return true;
default:
return false;
}
}
#endif
}
void ShowFeedbackPage(Browser* browser, void ShowFeedbackPage(Browser* browser,
FeedbackSource source, FeedbackSource source,
const std::string& description_template, const std::string& description_template,
...@@ -42,12 +70,25 @@ void ShowFeedbackPage(Browser* browser, ...@@ -42,12 +70,25 @@ void ShowFeedbackPage(Browser* browser,
extensions::FeedbackPrivateAPI* api = extensions::FeedbackPrivateAPI* api =
extensions::FeedbackPrivateAPI::GetFactoryInstance()->Get(profile); extensions::FeedbackPrivateAPI::GetFactoryInstance()->Get(profile);
api->RequestFeedbackForFlow( feedback_private::FeedbackFlow flow =
description_template, description_placeholder_text, category_tag,
extra_diagnostics, page_url,
source == kFeedbackSourceSadTabPage source == kFeedbackSourceSadTabPage
? feedback_private::FeedbackFlow::FEEDBACK_FLOW_SADTABCRASH ? feedback_private::FeedbackFlow::FEEDBACK_FLOW_SADTABCRASH
: feedback_private::FeedbackFlow::FEEDBACK_FLOW_REGULAR); : feedback_private::FeedbackFlow::FEEDBACK_FLOW_REGULAR;
#if defined(OS_CHROMEOS)
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile);
if (signin_manager &&
base::EndsWith(signin_manager->GetAuthenticatedAccountInfo().email,
kGoogleDotCom, base::CompareCase::INSENSITIVE_ASCII) &&
IsFromUserInteraction(source)) {
flow = feedback_private::FeedbackFlow::FEEDBACK_FLOW_GOOGLEINTERNAL;
}
#endif
api->RequestFeedbackForFlow(description_template,
description_placeholder_text, category_tag,
extra_diagnostics, page_url, flow);
} }
} // namespace chrome } // namespace chrome
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
<include name="IDR_HANGOUT_SERVICES_THUNK_JS" file="hangout_services/thunk.js" type="BINDATA" /> <include name="IDR_HANGOUT_SERVICES_THUNK_JS" file="hangout_services/thunk.js" type="BINDATA" />
</if> </if>
<if expr="not is_android"> <if expr="not is_android">
<include name="IDR_FEEDBACK_BLUETOOTHLOGSINFO_HTML" file="feedback/html/bluetooth_logs_info.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_FEEDBACK_DEFAULT_HTML" file="feedback/html/default.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_FEEDBACK_DEFAULT_HTML" file="feedback/html/default.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_FEEDBACK_SYSINFO_HTML" file="feedback/html/sys_info.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_FEEDBACK_SYSINFO_HTML" file="feedback/html/sys_info.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_FEEDBACK_FEEDBACK_DATA_JS" file="feedback/js/data.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_FEEDBACK_FEEDBACK_DATA_JS" file="feedback/js/data.js" flattenhtml="true" type="BINDATA" />
......
<!doctype html>
<html i18n-values="dir:textdirection;lang:language">
<head>
<script src="chrome://resources/js/i18n_template_no_process.js"></script>
</head>
<body>
<div id="bluetooth-logs-info-container">
<span i18n-content="bluetooth-logs-message"></span>
</div>
</body>
<html>
...@@ -81,6 +81,13 @@ ...@@ -81,6 +81,13 @@
</span> </span>
</div> </div>
<if expr="chromeos"> <if expr="chromeos">
<!-- Bluetooth Logs (Googler Internal Only) -->
<div id="bluetooth-checkbox-container" class="checkbox-field-container"
hidden>
<input id="bluetooth-logs-checkbox" type="checkbox" checked>
<label id="bluetooth-info-label"
i18n-values=".innerHTML:bluetooth-logs-info"></label>
</div>
<!-- Performance Feedback --> <!-- Performance Feedback -->
<div id="performance-info-area" hidden> <div id="performance-info-area" hidden>
<input id="performance-info-checkbox" type="checkbox"> <input id="performance-info-checkbox" type="checkbox">
......
...@@ -77,6 +77,28 @@ var isSystemInfoReady = false; ...@@ -77,6 +77,28 @@ var isSystemInfoReady = false;
*/ */
var isShowingSrtPrompt = false; var isShowingSrtPrompt = false;
/**
* Regular expression to check for all variants of bluetooth, blutooth, with or
* without space between the words and for BT when used as an individual word,
* or as two individual characters. Case insensitive matching.
* @type {RegExp}
*/
const btRegEx = new RegExp('[b]lu[e]?[ ]?tooth|\b[b][ ]?[t]\b', 'i');
/**
* Regular expression to check for all strings indicating that a user can't
* connect to a HID or Audio device. This is also a likely indication of a
* Bluetooth related issue.
* Sample strings this will match:
* "I can't connect the speaker!",
* "The keyboard has connection problem."
* @type {RegExp}
*/
const cantConnectRegEx = new RegExp(
'((headphones|keyboard|mouse|speaker)((?!connect).*)connect)|' +
'(connect.*(headphones|keyboard|mouse|speaker))',
'i');
/** /**
* The callback used by the sys_info_page to receive the event that the system * The callback used by the sys_info_page to receive the event that the system
* information is ready. * information is ready.
...@@ -158,6 +180,17 @@ function openSlowTraceWindow() { ...@@ -158,6 +180,17 @@ function openSlowTraceWindow() {
'chrome://slow_trace/tracing.zip#' + feedbackInfo.traceId); 'chrome://slow_trace/tracing.zip#' + feedbackInfo.traceId);
} }
/**
* Checks if any keywords related to bluetooth have been typed. If they are,
* we show the bluetooth logs option, otherwise hide it.
* @param {Event} inputEvent The input event for the description textarea.
*/
function checkForBluetoothKeywords(inputEvent) {
var isRelatedToBluetooth = btRegEx.test(inputEvent.target.value) ||
cantConnectRegEx.test(inputEvent.target.value);
$('bluetooth-checkbox-container').hidden = !isRelatedToBluetooth;
}
/** /**
* Sends the report; after the report is sent, we need to be redirected to * Sends the report; after the report is sent, we need to be redirected to
* the landing page, but we shouldn't be able to navigate back, hence * the landing page, but we shouldn't be able to navigate back, hence
...@@ -193,6 +226,11 @@ function sendReport() { ...@@ -193,6 +226,11 @@ function sendReport() {
useSystemInfo = useHistograms = true; useSystemInfo = useHistograms = true;
} }
// <if expr="chromeos"> // <if expr="chromeos">
if ($('bluetooth-logs-checkbox') != null &&
$('bluetooth-logs-checkbox').checked) {
feedbackInfo.sendBluetoothLogs = true;
feedbackInfo.categoryTag = 'BluetoothReportWithLogs';
}
if ($('performance-info-checkbox') == null || if ($('performance-info-checkbox') == null ||
!($('performance-info-checkbox').checked)) { !($('performance-info-checkbox').checked)) {
feedbackInfo.traceId = null; feedbackInfo.traceId = null;
...@@ -332,6 +370,12 @@ function initialize() { ...@@ -332,6 +370,12 @@ function initialize() {
chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.CLOSED); chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.CLOSED);
} }
}); });
} else if (
feedbackInfo.flow ==
chrome.feedbackPrivate.FeedbackFlow.GOOGLE_INTERNAL) {
$('description-text')
.addEventListener('input', checkForBluetoothKeywords);
$('srt-prompt').hidden = true;
} else { } else {
$('srt-prompt').hidden = true; $('srt-prompt').hidden = true;
} }
...@@ -491,6 +535,27 @@ function initialize() { ...@@ -491,6 +535,27 @@ function initialize() {
termsOfServiceUrlElement, FEEDBACK_TERM_OF_SERVICE_URL); termsOfServiceUrlElement, FEEDBACK_TERM_OF_SERVICE_URL);
} }
var bluetoothLogsInfoLinkElement = $('bluetooth-logs-info-link');
if (bluetoothLogsInfoLinkElement) {
bluetoothLogsInfoLinkElement.onclick = function(e) {
e.preventDefault();
chrome.app.window.create(
'/html/bluetooth_logs_info.html',
{width: 360, height: 120, resizable: false},
function(appWindow) {
appWindow.contentWindow.onload = function() {
i18nTemplate.process(
appWindow.contentWindow.document, loadTimeData);
};
});
bluetoothLogsInfoLinkElement.onauxclick = function(e) {
e.preventDefault();
};
};
}
// Make sure our focus starts on the description field. // Make sure our focus starts on the description field.
$('description-text').focus(); $('description-text').focus();
}); });
......
...@@ -313,10 +313,12 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() { ...@@ -313,10 +313,12 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() {
delegate->FetchAndMergeIwlwifiDumpLogsIfPresent( delegate->FetchAndMergeIwlwifiDumpLogsIfPresent(
std::move(sys_logs), browser_context(), std::move(sys_logs), browser_context(),
base::Bind(&FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched, this, base::Bind(&FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched, this,
feedback_data, feedback_info.send_histograms)); feedback_data, feedback_info.send_histograms,
feedback_info.send_bluetooth_logs &&
*feedback_info.send_bluetooth_logs));
#else #else
OnAllLogsFetched(feedback_data, feedback_info.send_histograms, OnAllLogsFetched(feedback_data, feedback_info.send_histograms,
std::move(sys_logs)); false /* send_bluetooth_logs */, std::move(sys_logs));
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
return RespondLater(); return RespondLater();
...@@ -325,6 +327,7 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() { ...@@ -325,6 +327,7 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() {
void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched( void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched(
scoped_refptr<FeedbackData> feedback_data, scoped_refptr<FeedbackData> feedback_data,
bool send_histograms, bool send_histograms,
bool send_bluetooth_logs,
std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) { std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) {
feedback_data->SetAndCompressSystemInfo(std::move(sys_logs)); feedback_data->SetAndCompressSystemInfo(std::move(sys_logs));
...@@ -341,6 +344,11 @@ void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched( ...@@ -341,6 +344,11 @@ void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched(
feedback_data->SetAndCompressHistograms(std::move(histograms)); feedback_data->SetAndCompressHistograms(std::move(histograms));
} }
if (send_bluetooth_logs) {
// TODO(rkc): Implement this once the platforms changes land.
LOG(WARNING) << "Not sending Bluetooth logs. Not implemented yet.";
}
service->SendFeedback( service->SendFeedback(
feedback_data, feedback_data,
base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this, base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this,
......
...@@ -141,6 +141,7 @@ class FeedbackPrivateSendFeedbackFunction : public UIThreadExtensionFunction { ...@@ -141,6 +141,7 @@ class FeedbackPrivateSendFeedbackFunction : public UIThreadExtensionFunction {
void OnAllLogsFetched( void OnAllLogsFetched(
scoped_refptr<feedback::FeedbackData> feedback_data, scoped_refptr<feedback::FeedbackData> feedback_data,
bool send_histograms, bool send_histograms,
bool send_bluetooth_logs,
std::unique_ptr<FeedbackCommon::SystemLogsMap> sys_logs); std::unique_ptr<FeedbackCommon::SystemLogsMap> sys_logs);
void OnCompleted(api::feedback_private::LandingPageType type, bool success); void OnCompleted(api::feedback_private::LandingPageType type, bool success);
}; };
......
...@@ -31,7 +31,10 @@ namespace feedbackPrivate { ...@@ -31,7 +31,10 @@ namespace feedbackPrivate {
// Flow when the feedback is requested from the sad tab ("Aw, Snap!") page // Flow when the feedback is requested from the sad tab ("Aw, Snap!") page
// when the renderer crashes. // when the renderer crashes.
sadTabCrash sadTabCrash,
// Flow for internal Google users.
googleInternal
}; };
dictionary FeedbackInfo { dictionary FeedbackInfo {
...@@ -82,6 +85,9 @@ namespace feedbackPrivate { ...@@ -82,6 +85,9 @@ namespace feedbackPrivate {
// Whether to use the system-provided window frame or custom frame controls. // Whether to use the system-provided window frame or custom frame controls.
boolean? useSystemWindowFrame; boolean? useSystemWindowFrame;
// Whether or not to send bluetooth logs with this report.
boolean? sendBluetoothLogs;
}; };
// Status of the sending of a feedback report. // Status of the sending of a feedback report.
......
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