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.">
<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
</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">
Feedback Report
</message>
......
......@@ -77,6 +77,8 @@ ChromeFeedbackPrivateDelegate::GetStrings(
SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE);
SET_STRING("performance-trace",
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.
SET_STRING("sysinfoPageTitle", IDS_FEEDBACK_SYSINFO_PAGE_TITLE);
SET_STRING("sysinfoPageDescription", IDS_ABOUT_SYS_DESC);
......
......@@ -5,6 +5,7 @@
#include <string>
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "chrome/browser/feedback/feedback_dialog_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
......@@ -13,10 +14,37 @@
#include "chrome/common/chrome_switches.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 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,
FeedbackSource source,
const std::string& description_template,
......@@ -42,12 +70,25 @@ void ShowFeedbackPage(Browser* browser,
extensions::FeedbackPrivateAPI* api =
extensions::FeedbackPrivateAPI::GetFactoryInstance()->Get(profile);
api->RequestFeedbackForFlow(
description_template, description_placeholder_text, category_tag,
extra_diagnostics, page_url,
feedback_private::FeedbackFlow flow =
source == kFeedbackSourceSadTabPage
? 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
......@@ -40,6 +40,7 @@
<include name="IDR_HANGOUT_SERVICES_THUNK_JS" file="hangout_services/thunk.js" type="BINDATA" />
</if>
<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_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" />
......
<!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 @@
</span>
</div>
<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 -->
<div id="performance-info-area" hidden>
<input id="performance-info-checkbox" type="checkbox">
......
......@@ -77,6 +77,28 @@ var isSystemInfoReady = 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
* information is ready.
......@@ -158,6 +180,17 @@ function openSlowTraceWindow() {
'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
* the landing page, but we shouldn't be able to navigate back, hence
......@@ -193,6 +226,11 @@ function sendReport() {
useSystemInfo = useHistograms = true;
}
// <if expr="chromeos">
if ($('bluetooth-logs-checkbox') != null &&
$('bluetooth-logs-checkbox').checked) {
feedbackInfo.sendBluetoothLogs = true;
feedbackInfo.categoryTag = 'BluetoothReportWithLogs';
}
if ($('performance-info-checkbox') == null ||
!($('performance-info-checkbox').checked)) {
feedbackInfo.traceId = null;
......@@ -332,6 +370,12 @@ function initialize() {
chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.CLOSED);
}
});
} else if (
feedbackInfo.flow ==
chrome.feedbackPrivate.FeedbackFlow.GOOGLE_INTERNAL) {
$('description-text')
.addEventListener('input', checkForBluetoothKeywords);
$('srt-prompt').hidden = true;
} else {
$('srt-prompt').hidden = true;
}
......@@ -491,6 +535,27 @@ function initialize() {
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.
$('description-text').focus();
});
......
......@@ -313,10 +313,12 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() {
delegate->FetchAndMergeIwlwifiDumpLogsIfPresent(
std::move(sys_logs), browser_context(),
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
OnAllLogsFetched(feedback_data, feedback_info.send_histograms,
std::move(sys_logs));
false /* send_bluetooth_logs */, std::move(sys_logs));
#endif // defined(OS_CHROMEOS)
return RespondLater();
......@@ -325,6 +327,7 @@ ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() {
void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched(
scoped_refptr<FeedbackData> feedback_data,
bool send_histograms,
bool send_bluetooth_logs,
std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) {
feedback_data->SetAndCompressSystemInfo(std::move(sys_logs));
......@@ -341,6 +344,11 @@ void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched(
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(
feedback_data,
base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this,
......
......@@ -141,6 +141,7 @@ class FeedbackPrivateSendFeedbackFunction : public UIThreadExtensionFunction {
void OnAllLogsFetched(
scoped_refptr<feedback::FeedbackData> feedback_data,
bool send_histograms,
bool send_bluetooth_logs,
std::unique_ptr<FeedbackCommon::SystemLogsMap> sys_logs);
void OnCompleted(api::feedback_private::LandingPageType type, bool success);
};
......
......@@ -31,7 +31,10 @@ namespace feedbackPrivate {
// Flow when the feedback is requested from the sad tab ("Aw, Snap!") page
// when the renderer crashes.
sadTabCrash
sadTabCrash,
// Flow for internal Google users.
googleInternal
};
dictionary FeedbackInfo {
......@@ -82,6 +85,9 @@ namespace feedbackPrivate {
// Whether to use the system-provided window frame or custom frame controls.
boolean? useSystemWindowFrame;
// Whether or not to send bluetooth logs with this report.
boolean? sendBluetoothLogs;
};
// 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