From 00ac54465f52affc70bf32d0b52def051a3bfe41 Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Mon, 9 Sep 2019 12:25:37 -0700 Subject: [PATCH 1/5] add webcompat reporter modal UI with story --- .../ui/components/basic/display.ts | 52 ++++++++++++++ .../ui/components/basic/index.ts | 20 ++++++ .../ui/components/basic/structure.ts | 38 +++++++++++ .../ui/stories/modal/fakeLocale.ts | 20 ++++++ .../ui/stories/modal/index.tsx | 46 +++++++++++++ .../modal/screens/ConfirmationView.tsx | 39 +++++++++++ .../ui/stories/modal/screens/ReportView.tsx | 67 +++++++++++++++++++ .../webcompat_reporter/ui/stories/story.tsx | 49 ++++++++++++++ 8 files changed, 331 insertions(+) create mode 100644 components/webcompat_reporter/ui/components/basic/display.ts create mode 100644 components/webcompat_reporter/ui/components/basic/index.ts create mode 100644 components/webcompat_reporter/ui/components/basic/structure.ts create mode 100644 components/webcompat_reporter/ui/stories/modal/fakeLocale.ts create mode 100644 components/webcompat_reporter/ui/stories/modal/index.tsx create mode 100644 components/webcompat_reporter/ui/stories/modal/screens/ConfirmationView.tsx create mode 100644 components/webcompat_reporter/ui/stories/modal/screens/ReportView.tsx create mode 100644 components/webcompat_reporter/ui/stories/story.tsx diff --git a/components/webcompat_reporter/ui/components/basic/display.ts b/components/webcompat_reporter/ui/components/basic/display.ts new file mode 100644 index 000000000000..8e4fb362ffd1 --- /dev/null +++ b/components/webcompat_reporter/ui/components/basic/display.ts @@ -0,0 +1,52 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'brave-ui/theme' +import { TextSection } from './structure' +import { CheckCircleIcon } from 'brave-ui/components/icons' + +export const ModalTitle = styled(TextSection)` + box-sizing: border-box; + font-size: 20px; + font-family: ${p => p.theme.fontFamily.heading}; + line-height: 20px; + font-weight: 500; + color: ${p => p.theme.color.text}; + margin: 0; +` + +export const InfoText = styled(TextSection)` + box-sizing: border-box; + color: ${p => p.theme.color.text}; + font-size: 14px; + font-family: ${p => p.theme.fontFamily.body}; + margin: 0; + line-height: 1.2; +` + +export const DisclaimerText = styled(TextSection)` + box-sizing: border-box; + color: ${p => p.theme.color.text}; + font-size: 12px; + font-family: ${p => p.theme.fontFamily.body}; + margin: 0; + line-height: 1.2; +` + +export const NonInteractiveURL = styled<{}, 'p'>('p')` + box-sizing: border-box; + color: ${p => p.theme.color.brandBrave}; + font-size: 14px; + font-weight: 500; + display: inline-block; + text-align: left; + width: fit-content; +` + +export const SuccessIcon = styled(CheckCircleIcon)` + color: ${p => p.theme.color.subtle}; + width: 30px; + margin-right: 10px; +` diff --git a/components/webcompat_reporter/ui/components/basic/index.ts b/components/webcompat_reporter/ui/components/basic/index.ts new file mode 100644 index 000000000000..0b2940ce4fcc --- /dev/null +++ b/components/webcompat_reporter/ui/components/basic/index.ts @@ -0,0 +1,20 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export { + SideBySideButtons, + ModalLayout, + PaddedButton, + TextSection, + IconTitle +} from './structure' + +export { + ModalTitle, + InfoText, + DisclaimerText, + NonInteractiveURL, + SuccessIcon +} from './display' diff --git a/components/webcompat_reporter/ui/components/basic/structure.ts b/components/webcompat_reporter/ui/components/basic/structure.ts new file mode 100644 index 000000000000..11477a960534 --- /dev/null +++ b/components/webcompat_reporter/ui/components/basic/structure.ts @@ -0,0 +1,38 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import styled from 'brave-ui/theme' +import Button, { Props as ButtonProps } from 'brave-ui/components/buttonsIndicators/button' + +export const SideBySideButtons = styled<{}, 'div'>('div')` + box-sizing: border-box; + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: 10px; +` + +export const ModalLayout = styled<{}, 'div'>('div')` + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: stretch; + justify-content: space-around; + min-height: 100px; +` + +export const PaddedButton = styled(Button as React.ComponentType)` + margin: 5px; +` + +export const TextSection = styled<{}, 'div'>('div')` + margin: 6px 0 !important; +` + +export const IconTitle = styled<{}, 'div'>('div')` + display: flex; + flex-direction: row; +` diff --git a/components/webcompat_reporter/ui/stories/modal/fakeLocale.ts b/components/webcompat_reporter/ui/stories/modal/fakeLocale.ts new file mode 100644 index 000000000000..0193c3971e5e --- /dev/null +++ b/components/webcompat_reporter/ui/stories/modal/fakeLocale.ts @@ -0,0 +1,20 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const locale: { [key: string]: string } = { + // Report modal + reportModalTitle: 'Report a broken site', + reportExplanation: 'Let Brave\'s developers know that this site doesn\'t work properly with Shields:', + reportDisclaimer: 'Note: This site address will be submitted with your Brave version number and your IP address (which will not be stored).', + cancel: 'Cancel', + submit: 'Submit', + // Confirmation modal + thankYou: 'Thank you!', + confirmationNotice: 'Thanks for letting Brave\'s developers know that there\'s something wrong with this site. We\'ll do our best to fix it!' +} + +export default locale + +export const getLocale = (word: string) => locale[word] diff --git a/components/webcompat_reporter/ui/stories/modal/index.tsx b/components/webcompat_reporter/ui/stories/modal/index.tsx new file mode 100644 index 000000000000..612b401bdc05 --- /dev/null +++ b/components/webcompat_reporter/ui/stories/modal/index.tsx @@ -0,0 +1,46 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import ReportView from './screens/ReportView' +import ConfirmationView from './screens/ConfirmationView' +import { Card } from 'brave-ui/components' + +interface Props { + siteUrl: string + submitted: boolean + onSubmitReport: () => void + onClose: () => void +} + +export default class WebcompatReportModal extends React.PureComponent { + constructor (props: Props) { + super(props) + } + + render () { + const { + siteUrl, + submitted, + onSubmitReport, + onClose + } = this.props + return ( + + {submitted ? ( + + ) : ( + + )} + + ) + } +} diff --git a/components/webcompat_reporter/ui/stories/modal/screens/ConfirmationView.tsx b/components/webcompat_reporter/ui/stories/modal/screens/ConfirmationView.tsx new file mode 100644 index 000000000000..4e84bc2a7dc9 --- /dev/null +++ b/components/webcompat_reporter/ui/stories/modal/screens/ConfirmationView.tsx @@ -0,0 +1,39 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import { + ModalLayout, + SuccessIcon, + IconTitle, + ModalTitle, + TextSection, + InfoText +} from '../../../components/basic' + +// Fake data +import { getLocale } from '../fakeLocale' + +export default class ConfirmationView extends React.PureComponent<{}, {}> { + constructor (props: {}) { + super(props) + } + + render () { + return ( + + + + {getLocale('thankYou')} + + + {getLocale('confirmationNotice')} + + + ) + } +} diff --git a/components/webcompat_reporter/ui/stories/modal/screens/ReportView.tsx b/components/webcompat_reporter/ui/stories/modal/screens/ReportView.tsx new file mode 100644 index 000000000000..234b9feac006 --- /dev/null +++ b/components/webcompat_reporter/ui/stories/modal/screens/ReportView.tsx @@ -0,0 +1,67 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import { + ModalLayout, + ModalTitle, + TextSection, + InfoText, + NonInteractiveURL, + DisclaimerText, + SideBySideButtons, + PaddedButton +} from '../../../components/basic' + +// Fake data +import { getLocale } from '../fakeLocale' + +interface Props { + siteUrl: string + onSubmitReport: () => void + onClose: () => void +} + +export default class ReportView extends React.PureComponent { + constructor (props: Props) { + super(props) + } + + render () { + const { + siteUrl, + onSubmitReport, + onClose + } = this.props + return ( + + + {getLocale('reportModalTitle')} + + {getLocale('reportExplanation')} + {siteUrl} + {getLocale('reportDisclaimer')} + + + + + + ) + } +} diff --git a/components/webcompat_reporter/ui/stories/story.tsx b/components/webcompat_reporter/ui/stories/story.tsx new file mode 100644 index 000000000000..8d8e8986e59e --- /dev/null +++ b/components/webcompat_reporter/ui/stories/story.tsx @@ -0,0 +1,49 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { storiesOf } from '@storybook/react' +import Theme from 'brave-ui/theme/brave-default' +import DarkTheme from 'brave-ui/theme/brave-dark' +import { withThemesProvider } from 'storybook-addon-styled-component-theme' +// @ts-ignore +import { boolean, number } from '@storybook/addon-knobs' + +// Components +import WebcompatReportModal from './modal/index' + +// Themes +const themes = [Theme, DarkTheme] + +storiesOf('Webcompat Reporter', module) + .addDecorator(withThemesProvider(themes)) + .add('Before submit', () => { + const fakeOnSubmit = () => { /* noop */ } + const fakeOnClose = () => { /* noop */ } + return ( +
+ +
+ ) + }) + .add('Submit confirmation', () => { + const fakeOnSubmit = () => { /* noop */ } + const fakeOnClose = () => { /* noop */ } + return ( +
+ +
+ ) + }) From 63f176c7e91478809bf837196e62ee9b76e58678 Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Tue, 10 Sep 2019 10:34:52 -0700 Subject: [PATCH 2/5] bring up reporter modal via new help menu option --- app/brave_command_ids.h | 1 + app/brave_generated_resources.grd | 3 + browser/resources/resource_ids | 4 + browser/ui/BUILD.gn | 4 + .../ui/brave_browser_command_controller.cc | 8 ++ browser/ui/brave_browser_command_controller.h | 1 + browser/ui/brave_pages.cc | 10 ++ browser/ui/brave_pages.h | 1 + browser/ui/toolbar/brave_app_menu_model.cc | 5 + .../webui/brave_web_ui_controller_factory.cc | 4 + browser/ui/webui/brave_webui_source.cc | 13 ++ browser/ui/webui/webcompat_reporter_ui.cc | 69 +++++++++++ browser/ui/webui/webcompat_reporter_ui.h | 27 +++++ browser/webcompat_reporter/BUILD.gn | 15 +++ .../webcompat_reporter_dialog.cc | 114 ++++++++++++++++++ .../webcompat_reporter_dialog.h | 15 +++ common/extensions/api/_api_features.json | 3 +- common/webui_url_constants.cc | 2 + common/webui_url_constants.h | 2 + components/common/typescript.gni | 1 + components/definitions/webcompatReporter.d.ts | 10 ++ components/resources/BUILD.gn | 2 + .../resources/brave_components_resources.grd | 4 + .../resources/brave_components_strings.grd | 9 ++ components/webcompat_reporter/ui/BUILD.gn | 17 +++ .../ui/actions/webcompatreporter_actions.ts | 21 ++++ .../ui/components/ConfirmationView.tsx | 39 ++++++ .../ui/components/ReportView.tsx | 67 ++++++++++ .../ui/components/WebcompatReportModal.tsx | 46 +++++++ .../ui/components/basic/display.ts | 5 + .../ui/components/basic/index.ts | 1 + .../ui/constants/webcompatreporter_types.ts | 10 ++ .../webcompat_reporter/ui/containers/App.tsx | 54 +++++++++ .../webcompat_reporter/ui/reducers/index.ts | 13 ++ .../ui/reducers/webcompatreporter_reducer.ts | 42 +++++++ components/webcompat_reporter/ui/store.ts | 11 ++ .../ui/stories/modal/index.tsx | 6 +- .../ui/webcompat_reporter.html | 21 ++++ .../ui/webcompat_reporter.tsx | 70 +++++++++++ 39 files changed, 746 insertions(+), 4 deletions(-) create mode 100644 browser/ui/webui/webcompat_reporter_ui.cc create mode 100644 browser/ui/webui/webcompat_reporter_ui.h create mode 100644 browser/webcompat_reporter/BUILD.gn create mode 100644 browser/webcompat_reporter/webcompat_reporter_dialog.cc create mode 100644 browser/webcompat_reporter/webcompat_reporter_dialog.h create mode 100644 components/definitions/webcompatReporter.d.ts create mode 100644 components/webcompat_reporter/ui/BUILD.gn create mode 100644 components/webcompat_reporter/ui/actions/webcompatreporter_actions.ts create mode 100644 components/webcompat_reporter/ui/components/ConfirmationView.tsx create mode 100644 components/webcompat_reporter/ui/components/ReportView.tsx create mode 100644 components/webcompat_reporter/ui/components/WebcompatReportModal.tsx create mode 100644 components/webcompat_reporter/ui/constants/webcompatreporter_types.ts create mode 100644 components/webcompat_reporter/ui/containers/App.tsx create mode 100644 components/webcompat_reporter/ui/reducers/index.ts create mode 100644 components/webcompat_reporter/ui/reducers/webcompatreporter_reducer.ts create mode 100644 components/webcompat_reporter/ui/store.ts create mode 100644 components/webcompat_reporter/ui/webcompat_reporter.html create mode 100644 components/webcompat_reporter/ui/webcompat_reporter.tsx diff --git a/app/brave_command_ids.h b/app/brave_command_ids.h index 3f5d75d32200..c2a310ba6b5a 100644 --- a/app/brave_command_ids.h +++ b/app/brave_command_ids.h @@ -19,6 +19,7 @@ #define IDC_SHOW_BRAVE_WALLET 56006 #define IDC_ADD_NEW_PROFILE 56007 #define IDC_OPEN_GUEST_PROFILE 56008 +#define IDC_SHOW_BRAVE_WEBCOMPAT_REPORTER 56009 #define IDC_BRAVE_COMMANDS_LAST 57000 diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd index 32d64d561f11..b01ddb04dddb 100644 --- a/app/brave_generated_resources.grd +++ b/app/brave_generated_resources.grd @@ -126,6 +126,9 @@ Brave Ad Block + + Report a Broken Site + Sync diff --git a/browser/resources/resource_ids b/browser/resources/resource_ids index a1335bc77948..f7205b7a558f 100644 --- a/browser/resources/resource_ids +++ b/browser/resources/resource_ids @@ -92,4 +92,8 @@ "<(ROOT_GEN_DIR)/brave/web-ui-brave_extension/brave_extension.grd": { "includes": [44500], }, + # This file is generated during the build. + "<(ROOT_GEN_DIR)/brave/web-ui-webcompat_reporter/webcompat_reporter.grd": { + "includes": [45000], + }, } diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index 9baaea97b81f..68ccfe62c1e5 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -13,6 +13,8 @@ source_set("ui") { "webui/basic_ui.h", "webui/brave_adblock_ui.cc", "webui/brave_adblock_ui.h", + "webui/webcompat_reporter_ui.cc", + "webui/webcompat_reporter_ui.h", "webui/brave_new_tab_message_handler.cc", "webui/brave_new_tab_message_handler.h", "webui/brave_new_tab_ui.cc", @@ -164,9 +166,11 @@ source_set("ui") { "//brave/browser/profiles", "//brave/browser/resources/settings:resources", "//brave/browser/tor", + "//brave/browser/webcompat_reporter", "//brave/common", "//brave/common:pref_names", "//brave/components/brave_adblock_ui:generated_resources", + "//brave/components/webcompat_reporter/ui:generated_resources", "//brave/components/brave_new_tab_ui:generated_resources", "//brave/components/brave_rewards/browser", "//brave/components/brave_rewards/resources", diff --git a/browser/ui/brave_browser_command_controller.cc b/browser/ui/brave_browser_command_controller.cc index b81c299c5952..535d9d3966a7 100644 --- a/browser/ui/brave_browser_command_controller.cc +++ b/browser/ui/brave_browser_command_controller.cc @@ -123,6 +123,7 @@ void BraveBrowserCommandController::InitBraveCommandState() { #endif } UpdateCommandForBraveAdblock(); + UpdateCommandForWebcompatReporter(); #if BUILDFLAG(ENABLE_TOR) UpdateCommandForTor(); #endif @@ -138,6 +139,10 @@ void BraveBrowserCommandController::UpdateCommandForBraveAdblock() { UpdateCommandEnabled(IDC_SHOW_BRAVE_ADBLOCK, true); } +void BraveBrowserCommandController::UpdateCommandForWebcompatReporter() { + UpdateCommandEnabled(IDC_SHOW_BRAVE_WEBCOMPAT_REPORTER, true); +} + void BraveBrowserCommandController::UpdateCommandForTor() { #if BUILDFLAG(ENABLE_TOR) const bool is_tor_enabled = !tor::TorProfileService::IsTorDisabled(); @@ -187,6 +192,9 @@ bool BraveBrowserCommandController::ExecuteBraveCommandWithDisposition( case IDC_SHOW_BRAVE_ADBLOCK: brave::ShowBraveAdblock(browser_); break; + case IDC_SHOW_BRAVE_WEBCOMPAT_REPORTER: + brave::ShowWebcompatReporter(browser_); + break; case IDC_NEW_OFFTHERECORD_WINDOW_TOR: brave::NewOffTheRecordWindowTor(browser_); break; diff --git a/browser/ui/brave_browser_command_controller.h b/browser/ui/brave_browser_command_controller.h index 045b8af4869e..ee6b63060056 100644 --- a/browser/ui/brave_browser_command_controller.h +++ b/browser/ui/brave_browser_command_controller.h @@ -31,6 +31,7 @@ class BraveBrowserCommandController : public chrome::BrowserCommandController { void InitBraveCommandState(); void UpdateCommandForBraveRewards(); void UpdateCommandForBraveAdblock(); + void UpdateCommandForWebcompatReporter(); void UpdateCommandForTor(); void UpdateCommandForBraveSync(); void UpdateCommandForBraveWallet(); diff --git a/browser/ui/brave_pages.cc b/browser/ui/brave_pages.cc index 9e626c2b998f..c0ce7b4482c9 100644 --- a/browser/ui/brave_pages.cc +++ b/browser/ui/brave_pages.cc @@ -5,6 +5,7 @@ #include "brave/browser/ui/brave_pages.h" +#include "brave/browser/webcompat_reporter/webcompat_reporter_dialog.h" #include "brave/common/webui_url_constants.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/singleton_tabs.h" @@ -24,6 +25,15 @@ void ShowBraveAdblock(Browser* browser) { GetSingletonTabNavigateParams(browser, GURL(kBraveUIAdblockURL))); } +void ShowWebcompatReporter(Browser* browser) { + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + if (!web_contents) + return; + + OpenWebcompatReporterDialog(web_contents); +} + void ShowBraveSync(Browser* browser) { ShowSingletonTabOverwritingNTP( browser, diff --git a/browser/ui/brave_pages.h b/browser/ui/brave_pages.h index 5b6a8f34d297..3662b86a79ad 100644 --- a/browser/ui/brave_pages.h +++ b/browser/ui/brave_pages.h @@ -11,6 +11,7 @@ class Browser; namespace brave { void ShowBraveAdblock(Browser* browser); +void ShowWebcompatReporter(Browser* browser); void ShowBraveRewards(Browser* browser); void ShowBraveSync(Browser* browser); void ShowBraveWallet(Browser* browser); diff --git a/browser/ui/toolbar/brave_app_menu_model.cc b/browser/ui/toolbar/brave_app_menu_model.cc index 90a437b10ad2..09d773b6690b 100644 --- a/browser/ui/toolbar/brave_app_menu_model.cc +++ b/browser/ui/toolbar/brave_app_menu_model.cc @@ -84,4 +84,9 @@ void BraveAppMenuModel::InsertBraveMenuItems() { IDC_NEW_OFFTHERECORD_WINDOW_TOR, IDS_NEW_OFFTHERECORD_WINDOW_TOR); } + + InsertItemWithStringIdAt( + GetIndexOfCommandId(IDC_ABOUT), + IDC_SHOW_BRAVE_WEBCOMPAT_REPORTER, + IDS_SHOW_BRAVE_WEBCOMPAT_REPORTER); } diff --git a/browser/ui/webui/brave_web_ui_controller_factory.cc b/browser/ui/webui/brave_web_ui_controller_factory.cc index e320081b39a8..1f5e5888d4c6 100644 --- a/browser/ui/webui/brave_web_ui_controller_factory.cc +++ b/browser/ui/webui/brave_web_ui_controller_factory.cc @@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "brave/browser/ui/webui/brave_adblock_ui.h" +#include "brave/browser/ui/webui/webcompat_reporter_ui.h" #include "brave/browser/ui/webui/brave_new_tab_ui.h" #include "brave/common/pref_names.h" #include "brave/common/webui_url_constants.h" @@ -61,6 +62,8 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { auto host = url.host_piece(); if (host == kAdblockHost) { return new BraveAdblockUI(web_ui, url.host()); + } else if (host == kWebcompatReporterHost) { + return new WebcompatReporterUI(web_ui, url.host()); #if BUILDFLAG(BRAVE_WALLET_ENABLED) } else if (host == kWalletHost) { return new BraveWalletUI(web_ui, url.host()); @@ -98,6 +101,7 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, const GURL& url) { if (url.host_piece() == kAdblockHost || + url.host_piece() == kWebcompatReporterHost || #if BUILDFLAG(BRAVE_WALLET_ENABLED) url.host_piece() == kWalletHost || #endif diff --git a/browser/ui/webui/brave_webui_source.cc b/browser/ui/webui/brave_webui_source.cc index 0deafdba8f69..42eaa6163da1 100644 --- a/browser/ui/webui/brave_webui_source.cc +++ b/browser/ui/webui/brave_webui_source.cc @@ -772,6 +772,19 @@ void CustomizeWebUIHTMLSource(const std::string &name, { "viewingId", IDS_BRAVE_REWARDS_INTERNALS_VIEWING_ID }, { "walletPaymentId", IDS_BRAVE_REWARDS_INTERNALS_WALLET_PAYMENT_ID }, } + }, { + std::string("webcompat"), { + // Report modal + { "reportModalTitle", IDS_BRAVE_WEBCOMPATREPORTER_REPORT_MODAL_TITLE }, + { "reportExplanation", IDS_BRAVE_WEBCOMPATREPORTER_REPORT_EXPLANATION }, + { "reportDisclaimer", IDS_BRAVE_WEBCOMPATREPORTER_REPORT_DISCLAIMER }, + { "cancel", IDS_BRAVE_WEBCOMPATREPORTER_CANCEL }, + { "submit", IDS_BRAVE_WEBCOMPATREPORTER_SUBMIT }, + // Confirmation modal + { "thankYou", IDS_BRAVE_WEBCOMPATREPORTER_THANK_YOU }, + { "confirmationNotice", + IDS_BRAVE_WEBCOMPATREPORTER_CONFIRMATION_NOTICE }, + } } }; AddLocalizedStringsBulk(source, localized_strings[name]); diff --git a/browser/ui/webui/webcompat_reporter_ui.cc b/browser/ui/webui/webcompat_reporter_ui.cc new file mode 100644 index 000000000000..d341cb53b60a --- /dev/null +++ b/browser/ui/webui/webcompat_reporter_ui.cc @@ -0,0 +1,69 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/ui/webui/webcompat_reporter_ui.h" + +#include + +#include "brave/browser/ui/webui/basic_ui.h" +#include "brave/common/webui_url_constants.h" +#include "brave/components/webcompat_reporter/resources/grit/webcompat_reporter_generated_map.h" +#include "chrome/browser/profiles/profile.h" +#include "components/grit/brave_components_resources.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace { + +class WebcompatReporterDOMHandler : public content::WebUIMessageHandler { + public: + WebcompatReporterDOMHandler(); + ~WebcompatReporterDOMHandler() override; + + // WebUIMessageHandler implementation. + void RegisterMessages() override; + + private: + void HandleSubmitReport(const base::ListValue* args); + + DISALLOW_COPY_AND_ASSIGN(WebcompatReporterDOMHandler); +}; + +WebcompatReporterDOMHandler::WebcompatReporterDOMHandler() {} + +WebcompatReporterDOMHandler::~WebcompatReporterDOMHandler() {} + +void WebcompatReporterDOMHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "webcompat_reporter.submitReport", + base::BindRepeating(&WebcompatReporterDOMHandler::HandleSubmitReport, + base::Unretained(this))); +} + +void WebcompatReporterDOMHandler::HandleSubmitReport( + const base::ListValue* args) { + DCHECK_EQ(args->GetSize(), 1U); + std::string site_url; + if (!args->GetString(0, &site_url)) + return; + LOG(INFO) << "Submitting webcompat report for " << site_url << std::endl; + // TODO actually submit the report +} + +} // namespace + +WebcompatReporterUI::WebcompatReporterUI(content::WebUI* web_ui, + const std::string& name) + : ConstrainedWebDialogUI(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource* data_source = CreateBasicUIHTMLSource( + profile, name, kWebcompatReporterGenerated, + kWebcompatReporterGeneratedSize, IDR_WEBCOMPAT_REPORTER_HTML); + content::WebUIDataSource::Add(profile, data_source); + + web_ui->AddMessageHandler(std::make_unique()); +} + +WebcompatReporterUI::~WebcompatReporterUI() {} diff --git a/browser/ui/webui/webcompat_reporter_ui.h b/browser/ui/webui/webcompat_reporter_ui.h new file mode 100644 index 000000000000..d06946df3bd0 --- /dev/null +++ b/browser/ui/webui/webcompat_reporter_ui.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_UI_WEBUI_WEBCOMPAT_REPORTER_UI_H_ +#define BRAVE_BROWSER_UI_WEBUI_WEBCOMPAT_REPORTER_UI_H_ + +#include + +#include "base/macros.h" +#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" + +namespace content { +class WebUI; +} + +class WebcompatReporterUI : public ConstrainedWebDialogUI { + public: + WebcompatReporterUI(content::WebUI* web_ui, const std::string& host); + ~WebcompatReporterUI() override; + + private: + DISALLOW_COPY_AND_ASSIGN(WebcompatReporterUI); +}; + +#endif // BRAVE_BROWSER_UI_WEBUI_WEBCOMPAT_REPORTER_UI_H_ diff --git a/browser/webcompat_reporter/BUILD.gn b/browser/webcompat_reporter/BUILD.gn new file mode 100644 index 000000000000..dd7595d114d3 --- /dev/null +++ b/browser/webcompat_reporter/BUILD.gn @@ -0,0 +1,15 @@ +import("//build/config/features.gni") + +source_set("webcompat_reporter") { + sources = [ + "webcompat_reporter_dialog.cc", + "webcompat_reporter_dialog.h", + ] + + deps = [ + "//base", + "//brave/common", + "//content/public/browser", + "//ui/web_dialogs", + ] +} diff --git a/browser/webcompat_reporter/webcompat_reporter_dialog.cc b/browser/webcompat_reporter/webcompat_reporter_dialog.cc new file mode 100644 index 000000000000..158f0e8abcb4 --- /dev/null +++ b/browser/webcompat_reporter/webcompat_reporter_dialog.cc @@ -0,0 +1,114 @@ +/* Copyright 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/webcompat_reporter/webcompat_reporter_dialog.h" + +#include +#include +#include +#include + +#include "base/json/json_writer.h" +#include "base/strings/string16.h" +#include "base/values.h" +#include "brave/common/webui_url_constants.h" +#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui_message_handler.h" +#include "ui/web_dialogs/web_dialog_delegate.h" +#include "url/gurl.h" + +using content::WebContents; +using content::WebUIMessageHandler; + +constexpr int kDialogMinHeight = 100; +constexpr int kDialogMaxHeight = 700; +constexpr int kDialogWidth = 375; + +// A ui::WebDialogDelegate that specifies the webcompat reporter's appearance. +class WebcompatReporterDialogDelegate : public ui::WebDialogDelegate { + public: + explicit WebcompatReporterDialogDelegate( + std::unique_ptr params); + ~WebcompatReporterDialogDelegate() override; + + ui::ModalType GetDialogModalType() const override; + base::string16 GetDialogTitle() const override; + GURL GetDialogContentURL() const override; + void GetWebUIMessageHandlers( + std::vector* handlers) const override; + void GetDialogSize(gfx::Size* size) const override; + std::string GetDialogArgs() const override; + void OnDialogClosed(const std::string& json_retval) override; + void OnCloseContents(WebContents* source, bool* out_close_dialog) override; + bool ShouldShowDialogTitle() const override; + + private: + std::unique_ptr params_; + + DISALLOW_COPY_AND_ASSIGN(WebcompatReporterDialogDelegate); +}; + +WebcompatReporterDialogDelegate::WebcompatReporterDialogDelegate( + std::unique_ptr params) + : params_(std::move(params)) {} + +WebcompatReporterDialogDelegate::~WebcompatReporterDialogDelegate() {} + +ui::ModalType WebcompatReporterDialogDelegate::GetDialogModalType() const { + // Not used, returning dummy value. + NOTREACHED(); + return ui::MODAL_TYPE_WINDOW; +} + +base::string16 WebcompatReporterDialogDelegate::GetDialogTitle() const { + // Only used on Windows? + return base::string16(); +} + +GURL WebcompatReporterDialogDelegate::GetDialogContentURL() const { + return GURL(kBraveUIWebcompatReporterURL); +} + +void WebcompatReporterDialogDelegate::GetWebUIMessageHandlers( + std::vector* /* handlers */) const { + // WebcompatReporterWebUI should add its own message handlers. +} + +void WebcompatReporterDialogDelegate::GetDialogSize(gfx::Size* size) const { + DCHECK(size); + size->SetSize(kDialogWidth, kDialogMaxHeight); +} + +std::string WebcompatReporterDialogDelegate::GetDialogArgs() const { + std::string json; + base::JSONWriter::Write(*params_, &json); + return json; +} + +void WebcompatReporterDialogDelegate::OnDialogClosed( + const std::string& /* json_retval */) {} + +void WebcompatReporterDialogDelegate::OnCloseContents(WebContents* /* source */, + bool* out_close_dialog) { + *out_close_dialog = true; +} + +bool WebcompatReporterDialogDelegate::ShouldShowDialogTitle() const { + return false; +} + +void OpenWebcompatReporterDialog(content::WebContents* initiator) { + GURL site_url = initiator->GetLastCommittedURL(); + auto params_dict = std::make_unique(); + params_dict->SetString("siteUrl", site_url.GetOrigin().spec()); + + gfx::Size min_size(kDialogWidth, kDialogMinHeight); + gfx::Size max_size(kDialogWidth, kDialogMaxHeight); + ShowConstrainedWebDialogWithAutoResize( + initiator->GetBrowserContext(), + std::make_unique(std::move(params_dict)), + initiator, min_size, max_size); +} diff --git a/browser/webcompat_reporter/webcompat_reporter_dialog.h b/browser/webcompat_reporter/webcompat_reporter_dialog.h new file mode 100644 index 000000000000..c37608dff950 --- /dev/null +++ b/browser/webcompat_reporter/webcompat_reporter_dialog.h @@ -0,0 +1,15 @@ +/* Copyright 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_WEBCOMPAT_REPORTER_WEBCOMPAT_REPORTER_DIALOG_H_ +#define BRAVE_BROWSER_WEBCOMPAT_REPORTER_WEBCOMPAT_REPORTER_DIALOG_H_ + +namespace content { +class WebContents; +} + +void OpenWebcompatReporterDialog(content::WebContents* initiator); + +#endif // BRAVE_BROWSER_WEBCOMPAT_REPORTER_WEBCOMPAT_REPORTER_DIALOG_H_ diff --git a/common/extensions/api/_api_features.json b/common/extensions/api/_api_features.json index 07b1028c9e33..5d4b0c0ebced 100644 --- a/common/extensions/api/_api_features.json +++ b/common/extensions/api/_api_features.json @@ -115,7 +115,8 @@ "matches": [ "chrome://welcome/*", "chrome://settings/*", - "chrome://newtab/*" + "chrome://newtab/*", + "chrome://webcompat/*" ] }] } diff --git a/common/webui_url_constants.cc b/common/webui_url_constants.cc index e0699662a821..c1c88b294130 100644 --- a/common/webui_url_constants.cc +++ b/common/webui_url_constants.cc @@ -7,6 +7,7 @@ const char kAdblockHost[] = "adblock"; const char kAdblockJS[] = "brave_adblock.js"; +const char kWebcompatReporterHost[] = "webcompat"; const char kRewardsPageHost[] = "rewards"; const char kRewardsInternalsHost[] = "rewards-internals"; const char kWelcomeHost[] = "welcome"; @@ -17,6 +18,7 @@ const char kBraveUISyncHost[] = "sync"; const char kBraveSyncJS[] = "brave_sync.js"; const char kBraveUIRewardsURL[] = "chrome://rewards/"; const char kBraveUIAdblockURL[] = "chrome://adblock/"; +const char kBraveUIWebcompatReporterURL[] = "chrome://webcompat/"; const char kBraveUITipURL[] = "chrome://tip/"; const char kBraveUISyncURL[] = "chrome://sync/"; const char kBraveUIWalletURL[] = "chrome://wallet/"; diff --git a/common/webui_url_constants.h b/common/webui_url_constants.h index 0a435ceafe5b..ee58bc6d77fd 100644 --- a/common/webui_url_constants.h +++ b/common/webui_url_constants.h @@ -8,6 +8,7 @@ extern const char kAdblockHost[]; extern const char kAdblockJS[]; +extern const char kWebcompatReporterHost[]; extern const char kRewardsPageHost[]; extern const char kRewardsInternalsHost[]; extern const char kWelcomeHost[]; @@ -18,6 +19,7 @@ extern const char kBraveUISyncHost[]; extern const char kBraveSyncJS[]; extern const char kBraveUIRewardsURL[]; extern const char kBraveUIAdblockURL[]; +extern const char kBraveUIWebcompatReporterURL[]; extern const char kBraveUITipHost[]; extern const char kBraveUITipURL[]; extern const char kBraveUISyncURL[]; diff --git a/components/common/typescript.gni b/components/common/typescript.gni index ff47ce463286..adaa0243285c 100644 --- a/components/common/typescript.gni +++ b/components/common/typescript.gni @@ -9,6 +9,7 @@ brave_common_web_compile_inputs = [ rebase_path("BraveCoreThemeProvider.tsx"), # common definitions change rebase_path("../definitions/adBlock.d.ts"), + rebase_path("../definitions/webcompatReporter.d.ts"), rebase_path("../definitions/chromel.d.ts"), rebase_path("../definitions/global.d.ts"), rebase_path("../definitions/newTab.d.ts"), diff --git a/components/definitions/webcompatReporter.d.ts b/components/definitions/webcompatReporter.d.ts new file mode 100644 index 000000000000..90508ea4737c --- /dev/null +++ b/components/definitions/webcompatReporter.d.ts @@ -0,0 +1,10 @@ +declare namespace WebcompatReporter { + export interface ApplicationState { + reporterState: State | undefined + } + + export interface State { + siteUrl: string + submitted: boolean + } +} diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index 0d6b107c47a9..2037657cb466 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn @@ -46,6 +46,7 @@ repack("resources") { deps = [ ":static_resources", "//brave/components/brave_adblock_ui:generated_resources", + "//brave/components/webcompat_reporter/ui:generated_resources", "//brave/components/brave_new_tab_ui:generated_resources", "//brave/components/brave_welcome_ui:generated_resources", ] @@ -53,6 +54,7 @@ repack("resources") { sources = [ "$root_gen_dir/components/brave_components_static.pak", "$root_gen_dir/brave/components/brave_adblock/resources/brave_adblock_generated.pak", + "$root_gen_dir/brave/components/webcompat_reporter/resources/webcompat_reporter_generated.pak", "$root_gen_dir/brave/components/brave_new_tab/resources/brave_new_tab_generated.pak", "$root_gen_dir/brave/components/brave_welcome/resources/brave_welcome_generated.pak", ] diff --git a/components/resources/brave_components_resources.grd b/components/resources/brave_components_resources.grd index 579ac3099bc0..7d11f09d89c0 100644 --- a/components/resources/brave_components_resources.grd +++ b/components/resources/brave_components_resources.grd @@ -18,6 +18,10 @@ + + + + diff --git a/components/resources/brave_components_strings.grd b/components/resources/brave_components_strings.grd index afe7f228f465..77f7944613b4 100644 --- a/components/resources/brave_components_strings.grd +++ b/components/resources/brave_components_strings.grd @@ -174,6 +174,15 @@ Custom Filters One per line, a filter is described in Adblock Plus filter syntax + + Report a broken site + Let Brave's developers know that this site doesn't work properly with Shields: + Note: This site address will be submitted with your Brave version number and your IP address (which will not be stored). + Cancel + Submit + Thank you! + Thanks for letting Brave's developers know that there's something wrong with this site. We'll do our best to fix it! + Brave the new Internet Get ready to enjoy a faster and more secure browsing experience with a browser built to protect your privacy. diff --git a/components/webcompat_reporter/ui/BUILD.gn b/components/webcompat_reporter/ui/BUILD.gn new file mode 100644 index 000000000000..7e1b62151267 --- /dev/null +++ b/components/webcompat_reporter/ui/BUILD.gn @@ -0,0 +1,17 @@ +import("//brave/components/common/typescript.gni") + +transpile_web_ui("ui") { + entry_points = [ + ["webcompat_reporter", rebase_path("webcompat_reporter.tsx")] + ] + + resource_name = "webcompat_reporter" +} + +pack_web_resources("generated_resources") { + resource_name = "webcompat_reporter" + output_dir = "$root_gen_dir/brave/components/webcompat_reporter/resources" + deps = [ + ":ui" + ] +} diff --git a/components/webcompat_reporter/ui/actions/webcompatreporter_actions.ts b/components/webcompat_reporter/ui/actions/webcompatreporter_actions.ts new file mode 100644 index 000000000000..a1b12d853e31 --- /dev/null +++ b/components/webcompat_reporter/ui/actions/webcompatreporter_actions.ts @@ -0,0 +1,21 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { action } from 'typesafe-actions' + +// Constants +import { types } from '../constants/webcompatreporter_types' + +export const setSiteUrl = (siteUrl: string) => { + return action(types.WEBCOMPATREPORTER_SET_SITE_URL, { + siteUrl + }) +} + +export const onSubmitReport = () => + action(types.WEBCOMPATREPORTER_ON_SUBMIT_REPORT) + +export const onClose = () => + action(types.WEBCOMPATREPORTER_ON_CLOSE) diff --git a/components/webcompat_reporter/ui/components/ConfirmationView.tsx b/components/webcompat_reporter/ui/components/ConfirmationView.tsx new file mode 100644 index 000000000000..d5e9bac865c2 --- /dev/null +++ b/components/webcompat_reporter/ui/components/ConfirmationView.tsx @@ -0,0 +1,39 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import { + ModalLayout, + SuccessIcon, + IconTitle, + ModalTitle, + TextSection, + InfoText +} from './basic' + +// Localization data +import { getLocale } from '../../../common/locale' + +export default class ConfirmationView extends React.PureComponent<{}, {}> { + constructor (props: {}) { + super(props) + } + + render () { + return ( + + + + {getLocale('thankYou')} + + + {getLocale('confirmationNotice')} + + + ) + } +} diff --git a/components/webcompat_reporter/ui/components/ReportView.tsx b/components/webcompat_reporter/ui/components/ReportView.tsx new file mode 100644 index 000000000000..739e8d480f98 --- /dev/null +++ b/components/webcompat_reporter/ui/components/ReportView.tsx @@ -0,0 +1,67 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import { + ModalLayout, + ModalTitle, + TextSection, + InfoText, + NonInteractiveURL, + DisclaimerText, + SideBySideButtons, + PaddedButton +} from './basic' + +// Localization data +import { getLocale } from '../../../common/locale' + +interface Props { + siteUrl: string + onSubmitReport: () => void + onClose: () => void +} + +export default class ReportView extends React.PureComponent { + constructor (props: Props) { + super(props) + } + + render () { + const { + siteUrl, + onSubmitReport, + onClose + } = this.props + return ( + + + {getLocale('reportModalTitle')} + + {getLocale('reportExplanation')} + {siteUrl} + {getLocale('reportDisclaimer')} + + + + + + ) + } +} diff --git a/components/webcompat_reporter/ui/components/WebcompatReportModal.tsx b/components/webcompat_reporter/ui/components/WebcompatReportModal.tsx new file mode 100644 index 000000000000..3aeebfc1e59e --- /dev/null +++ b/components/webcompat_reporter/ui/components/WebcompatReportModal.tsx @@ -0,0 +1,46 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +// Components group +import ReportView from './ReportView' +import ConfirmationView from './ConfirmationView' +import { RectangularCard } from './basic' + +interface Props { + siteUrl: string + submitted: boolean + onSubmitReport: () => void + onClose: () => void +} + +export default class WebcompatReportModal extends React.PureComponent { + constructor (props: Props) { + super(props) + } + + render () { + const { + siteUrl, + submitted, + onSubmitReport, + onClose + } = this.props + return ( + + {submitted ? ( + + ) : ( + + )} + + ) + } +} diff --git a/components/webcompat_reporter/ui/components/basic/display.ts b/components/webcompat_reporter/ui/components/basic/display.ts index 8e4fb362ffd1..e8c2a1d59c75 100644 --- a/components/webcompat_reporter/ui/components/basic/display.ts +++ b/components/webcompat_reporter/ui/components/basic/display.ts @@ -6,6 +6,7 @@ import styled from 'brave-ui/theme' import { TextSection } from './structure' import { CheckCircleIcon } from 'brave-ui/components/icons' +import { Card } from 'brave-ui/components' export const ModalTitle = styled(TextSection)` box-sizing: border-box; @@ -50,3 +51,7 @@ export const SuccessIcon = styled(CheckCircleIcon)` width: 30px; margin-right: 10px; ` + +export const RectangularCard = styled(Card)` + border-radius: 0; +` diff --git a/components/webcompat_reporter/ui/components/basic/index.ts b/components/webcompat_reporter/ui/components/basic/index.ts index 0b2940ce4fcc..1ead8f0f8da9 100644 --- a/components/webcompat_reporter/ui/components/basic/index.ts +++ b/components/webcompat_reporter/ui/components/basic/index.ts @@ -12,6 +12,7 @@ export { } from './structure' export { + RectangularCard, ModalTitle, InfoText, DisclaimerText, diff --git a/components/webcompat_reporter/ui/constants/webcompatreporter_types.ts b/components/webcompat_reporter/ui/constants/webcompatreporter_types.ts new file mode 100644 index 000000000000..202919707124 --- /dev/null +++ b/components/webcompat_reporter/ui/constants/webcompatreporter_types.ts @@ -0,0 +1,10 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +export const enum types { + WEBCOMPATREPORTER_ON_SUBMIT_REPORT = '@@webcompatreporter/WEBCOMPATREPORTER_ON_SUBMIT_REPORT', + WEBCOMPATREPORTER_SET_SITE_URL = '@@webcompatreporter/WEBCOMPATREPORTER_SET_SITE_URL', + WEBCOMPATREPORTER_ON_CLOSE = '@@webcompatreporter/WEBCOMPATREPORTER_ON_CLOSE' +} diff --git a/components/webcompat_reporter/ui/containers/App.tsx b/components/webcompat_reporter/ui/containers/App.tsx new file mode 100644 index 000000000000..4ec83277a617 --- /dev/null +++ b/components/webcompat_reporter/ui/containers/App.tsx @@ -0,0 +1,54 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { bindActionCreators, Dispatch } from 'redux' +import { connect } from 'react-redux' + +// Components +import WebcompatReportModal from '../components/WebcompatReportModal' + +// Utils +import * as webcompatReporterActions from '../actions/webcompatreporter_actions' + +interface Props { + actions: any + reporterState: WebcompatReporter.State +} + +class WebcompatReportContainer extends React.Component { + constructor (props: Props) { + super(props) + } + + get actions () { + return this.props.actions + } + + render () { + const { actions, reporterState } = this.props + return ( + + ) + } +} + +const mapStateToProps = (state: WebcompatReporter.ApplicationState) => ({ + reporterState: state.reporterState +}) + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + actions: bindActionCreators(webcompatReporterActions, dispatch) +}) + +export default connect( + mapStateToProps, + mapDispatchToProps +)(WebcompatReportContainer) diff --git a/components/webcompat_reporter/ui/reducers/index.ts b/components/webcompat_reporter/ui/reducers/index.ts new file mode 100644 index 000000000000..dfd86a624063 --- /dev/null +++ b/components/webcompat_reporter/ui/reducers/index.ts @@ -0,0 +1,13 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { combineReducers } from 'redux' + +// Utils +import webcompatReporterReducer from './webcompatreporter_reducer' + +export default combineReducers({ + reporterState: webcompatReporterReducer +}) diff --git a/components/webcompat_reporter/ui/reducers/webcompatreporter_reducer.ts b/components/webcompat_reporter/ui/reducers/webcompatreporter_reducer.ts new file mode 100644 index 000000000000..01e5ef3a11d4 --- /dev/null +++ b/components/webcompat_reporter/ui/reducers/webcompatreporter_reducer.ts @@ -0,0 +1,42 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { Reducer } from 'redux' + +// Constants +import { types } from '../constants/webcompatreporter_types' + +const defaultState: WebcompatReporter.State = { + siteUrl: '', + submitted: false +} + +const webcompatReporterReducer: Reducer = (state: WebcompatReporter.State = defaultState, action) => { + switch (action.type) { + case types.WEBCOMPATREPORTER_ON_SUBMIT_REPORT: + chrome.send('webcompat_reporter.submitReport', [state.siteUrl]) + state = { + ...state, + submitted: true + } + setTimeout(() => chrome.send('dialogClose'), 5000) + break + case types.WEBCOMPATREPORTER_SET_SITE_URL: + state = { + ...state, + siteUrl: action.payload.siteUrl + } + break + case types.WEBCOMPATREPORTER_ON_CLOSE: + chrome.send('dialogClose') + break + default: + break + } + + return state +} + +export default webcompatReporterReducer diff --git a/components/webcompat_reporter/ui/store.ts b/components/webcompat_reporter/ui/store.ts new file mode 100644 index 000000000000..caa1d3f22ce8 --- /dev/null +++ b/components/webcompat_reporter/ui/store.ts @@ -0,0 +1,11 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { createStore } from 'redux' + +// Utils +import reducers from './reducers' + +export default createStore(reducers) diff --git a/components/webcompat_reporter/ui/stories/modal/index.tsx b/components/webcompat_reporter/ui/stories/modal/index.tsx index 612b401bdc05..74a5ce85b2c1 100644 --- a/components/webcompat_reporter/ui/stories/modal/index.tsx +++ b/components/webcompat_reporter/ui/stories/modal/index.tsx @@ -8,7 +8,7 @@ import * as React from 'react' // Components group import ReportView from './screens/ReportView' import ConfirmationView from './screens/ConfirmationView' -import { Card } from 'brave-ui/components' +import { RectangularCard } from '../../components/basic/display' interface Props { siteUrl: string @@ -30,7 +30,7 @@ export default class WebcompatReportModal extends React.PureComponent onClose } = this.props return ( - + {submitted ? ( ) : ( @@ -40,7 +40,7 @@ export default class WebcompatReportModal extends React.PureComponent onClose={onClose} /> )} - + ) } } diff --git a/components/webcompat_reporter/ui/webcompat_reporter.html b/components/webcompat_reporter/ui/webcompat_reporter.html new file mode 100644 index 000000000000..1e513fa588e4 --- /dev/null +++ b/components/webcompat_reporter/ui/webcompat_reporter.html @@ -0,0 +1,21 @@ + + + + + +Webcompat Reporter + + + + + + + + + +
+ + diff --git a/components/webcompat_reporter/ui/webcompat_reporter.tsx b/components/webcompat_reporter/ui/webcompat_reporter.tsx new file mode 100644 index 000000000000..fb8318a55607 --- /dev/null +++ b/components/webcompat_reporter/ui/webcompat_reporter.tsx @@ -0,0 +1,70 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' +import { render } from 'react-dom' +import { Provider } from 'react-redux' +import { bindActionCreators } from 'redux' + +import Theme from 'brave-ui/theme/brave-default' +import DarkTheme from 'brave-ui/theme/brave-dark' +import BraveCoreThemeProvider from '../../common/BraveCoreThemeProvider' +require('../../../ui/webui/resources/fonts/muli.css') +require('../../../ui/webui/resources/fonts/poppins.css') + +// Containers +import App from './containers/App' + +// Utils +import store from './store' +import * as webcompatReporterActions from './actions/webcompatreporter_actions' + +let actions: any + +function getActions () { + if (actions) { + return actions + } + + actions = bindActionCreators(webcompatReporterActions, store.dispatch.bind(store)) + return actions +} + +function loadDialogArgs () { + const dialogArgsRaw = chrome.getVariableValue('dialogArguments') + let dialogArgs + try { + dialogArgs = JSON.parse(dialogArgsRaw) + } catch (e) { + console.error('Error parsing incoming dialog args: ', dialogArgsRaw, e) + } + + getActions().setSiteUrl(dialogArgs.siteUrl) +} + +function initialize () { + loadDialogArgs() + + new Promise(resolve => chrome.braveTheme.getBraveThemeType(resolve)) + .then((themeType: chrome.braveTheme.ThemeType) => { + render( + + + + + , + document.getElementById('root') + ) + }) + .catch(error => { + console.error('Problem mounting webcompat reporter modal', error) + }) +} + +document.addEventListener('DOMContentLoaded', initialize) From b792e88a7aa03d91cdfb0194339c3b9544428e3e Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Wed, 11 Sep 2019 12:05:57 -0700 Subject: [PATCH 3/5] allow uploading the broken site report --- browser/ui/BUILD.gn | 2 +- browser/ui/webui/webcompat_reporter_ui.cc | 12 ++- .../browser/brave_referrals_service.cc | 19 ++-- .../browser/brave_referrals_service.h | 2 + .../webcompat_reporter/browser/BUILD.gn | 29 ++++++ .../browser/webcompat_report_uploader.cc | 98 +++++++++++++++++++ .../browser/webcompat_report_uploader.h | 43 ++++++++ 7 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 components/webcompat_reporter/browser/BUILD.gn create mode 100644 components/webcompat_reporter/browser/webcompat_report_uploader.cc create mode 100644 components/webcompat_reporter/browser/webcompat_report_uploader.h diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index 68ccfe62c1e5..1fe36bd9b439 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -166,7 +166,7 @@ source_set("ui") { "//brave/browser/profiles", "//brave/browser/resources/settings:resources", "//brave/browser/tor", - "//brave/browser/webcompat_reporter", + "//brave/components/webcompat_reporter/browser", "//brave/common", "//brave/common:pref_names", "//brave/components/brave_adblock_ui:generated_resources", diff --git a/browser/ui/webui/webcompat_reporter_ui.cc b/browser/ui/webui/webcompat_reporter_ui.cc index d341cb53b60a..fec1a5be9c52 100644 --- a/browser/ui/webui/webcompat_reporter_ui.cc +++ b/browser/ui/webui/webcompat_reporter_ui.cc @@ -10,11 +10,14 @@ #include "brave/browser/ui/webui/basic_ui.h" #include "brave/common/webui_url_constants.h" #include "brave/components/webcompat_reporter/resources/grit/webcompat_reporter_generated_map.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "components/grit/brave_components_resources.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "brave/components/webcompat_reporter/browser/webcompat_report_uploader.h" + namespace { class WebcompatReporterDOMHandler : public content::WebUIMessageHandler { @@ -27,11 +30,14 @@ class WebcompatReporterDOMHandler : public content::WebUIMessageHandler { private: void HandleSubmitReport(const base::ListValue* args); + std::unique_ptr uploader_; DISALLOW_COPY_AND_ASSIGN(WebcompatReporterDOMHandler); }; -WebcompatReporterDOMHandler::WebcompatReporterDOMHandler() {} +WebcompatReporterDOMHandler::WebcompatReporterDOMHandler() + : uploader_(std::make_unique( + g_browser_process->shared_url_loader_factory())) {} WebcompatReporterDOMHandler::~WebcompatReporterDOMHandler() {} @@ -48,8 +54,8 @@ void WebcompatReporterDOMHandler::HandleSubmitReport( std::string site_url; if (!args->GetString(0, &site_url)) return; - LOG(INFO) << "Submitting webcompat report for " << site_url << std::endl; - // TODO actually submit the report + + uploader_->SubmitReport(site_url); } } // namespace diff --git a/components/brave_referrals/browser/brave_referrals_service.cc b/components/brave_referrals/browser/brave_referrals_service.cc index d370e521d7e8..af852651b871 100644 --- a/components/brave_referrals/browser/brave_referrals_service.cc +++ b/components/brave_referrals/browser/brave_referrals_service.cc @@ -93,6 +93,15 @@ std::string BuildReferralEndpoint(const std::string& path) { namespace brave { +std::string GetAPIKey() { + std::string api_key = BRAVE_REFERRALS_API_KEY; + std::unique_ptr env(base::Environment::Create()); + if (env->HasVar("BRAVE_REFERRALS_API_KEY")) + env->GetVar("BRAVE_REFERRALS_API_KEY", &api_key); + + return api_key; +} + BraveReferralsService::BraveReferralsService(PrefService* pref_service) : initialized_(false), task_runner_(base::CreateSequencedTaskRunner( @@ -470,10 +479,7 @@ void BraveReferralsService::MaybeDeletePromoCodePref() const { } std::string BraveReferralsService::BuildReferralInitPayload() const { - std::string api_key = BRAVE_REFERRALS_API_KEY; - std::unique_ptr env(base::Environment::Create()); - if (env->HasVar("BRAVE_REFERRALS_API_KEY")) - env->GetVar("BRAVE_REFERRALS_API_KEY", &api_key); + std::string api_key = GetAPIKey(); base::Value root(base::Value::Type::DICTIONARY); root.SetKey("api_key", base::Value(api_key)); @@ -488,10 +494,7 @@ std::string BraveReferralsService::BuildReferralInitPayload() const { std::string BraveReferralsService::BuildReferralFinalizationCheckPayload() const { - std::string api_key = BRAVE_REFERRALS_API_KEY; - std::unique_ptr env(base::Environment::Create()); - if (env->HasVar("BRAVE_REFERRALS_API_KEY")) - env->GetVar("BRAVE_REFERRALS_API_KEY", &api_key); + std::string api_key = GetAPIKey(); base::Value root(base::Value::Type::DICTIONARY); root.SetKey("api_key", base::Value(api_key)); diff --git a/components/brave_referrals/browser/brave_referrals_service.h b/components/brave_referrals/browser/brave_referrals_service.h index 5ed870aa594e..a4b431855be0 100644 --- a/components/brave_referrals/browser/brave_referrals_service.h +++ b/components/brave_referrals/browser/brave_referrals_service.h @@ -26,6 +26,8 @@ class SimpleURLLoader; namespace brave { +std::string GetAPIKey(); + class BraveReferralsService { public: explicit BraveReferralsService(PrefService* pref_service); diff --git a/components/webcompat_reporter/browser/BUILD.gn b/components/webcompat_reporter/browser/BUILD.gn new file mode 100644 index 000000000000..0d1cc0b273c1 --- /dev/null +++ b/components/webcompat_reporter/browser/BUILD.gn @@ -0,0 +1,29 @@ +import("//build/config/features.gni") + +declare_args() { + webcompat_report_api_endpoint = "https://webcompat.brave.com/1/webcompat" +} + +config("webcompat_reporter_config") { + defines = [ + "WEBCOMPAT_REPORT_ENDPOINT=\"$webcompat_report_api_endpoint\"" + ] +} + +source_set("browser") { + public_configs = [ ":webcompat_reporter_config" ] + + sources = [ + "webcompat_report_uploader.cc", + "webcompat_report_uploader.h", + ] + + deps = [ + "//base", + "//net", + "//content/public/browser", + "//services/network/public/cpp", + "//brave/components/brave_referrals/browser", + "//brave/common", + ] +} diff --git a/components/webcompat_reporter/browser/webcompat_report_uploader.cc b/components/webcompat_reporter/browser/webcompat_report_uploader.cc new file mode 100644 index 000000000000..94d063a79cbe --- /dev/null +++ b/components/webcompat_reporter/browser/webcompat_report_uploader.cc @@ -0,0 +1,98 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/components/webcompat_reporter/browser/webcompat_report_uploader.h" + +#include +#include +#include + +#include "base/environment.h" +#include "base/json/json_writer.h" +#include "brave/components/brave_referrals/browser/brave_referrals_service.h" +#include "content/public/browser/browser_task_traits.h" +#include "net/base/load_flags.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "url/gurl.h" + +namespace brave { + +WebcompatReportUploader::WebcompatReportUploader( + scoped_refptr factory) + : shared_url_loader_factory_(std::move(factory)) {} + +WebcompatReportUploader::~WebcompatReportUploader() {} + +void WebcompatReportUploader::SubmitReport(std::string report_domain) { + std::string api_key = brave::GetAPIKey(); + + GURL upload_url(WEBCOMPAT_REPORT_ENDPOINT); + + base::Value post_data_obj(base::Value::Type::DICTIONARY); + post_data_obj.SetKey("domain", base::Value(report_domain)); + post_data_obj.SetKey("api_key", base::Value(api_key)); + + std::string post_data; + base::JSONWriter::Write(post_data_obj, &post_data); + + WebcompatReportUploader::CreateAndStartURLLoader(upload_url, post_data); +} + +void WebcompatReportUploader::CreateAndStartURLLoader( + const GURL& upload_url, + const std::string& post_data) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + std::string content_type = "application/json"; + auto resource_request = std::make_unique(); + resource_request->url = GURL(upload_url); + resource_request->method = "POST"; + resource_request->load_flags = + net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_BYPASS_CACHE | + net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_AUTH_DATA; + + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("background_performance_tracer", R"( + semantics { + sender: "Brave Web Compatibility Reporting" + description: + "A user-initiated report of a website that appears broken as a" + "result of having Brave Shields enabled." + trigger: + "Though the 'Report a Broken Site' option of the help menu or" + "the Brave Shields panel." + data: "Broken domain and IP address." + destination: OTHER + destination_other: "Brave developers" + } + policy { + cookies_allowed: NO + })"); + + simple_url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), traffic_annotation); + simple_url_loader_->AttachStringForUpload(post_data, content_type); + simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + shared_url_loader_factory_.get(), + base::BindOnce(&WebcompatReportUploader::OnSimpleURLLoaderComplete, + base::Unretained(this))); +} + +void WebcompatReportUploader::OnSimpleURLLoaderComplete( + std::unique_ptr response_body) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + bool success = !!response_body; + + if (success) { + LOG(INFO) << "Successfully uploaded webcompat report. Thanks!" << std::endl; + } else { + LOG(ERROR) << "Uploading webcompat report failed - please try again later!" + << std::endl; + } +} + +} // namespace brave diff --git a/components/webcompat_reporter/browser/webcompat_report_uploader.h b/components/webcompat_reporter/browser/webcompat_report_uploader.h new file mode 100644 index 000000000000..96a99fd683a4 --- /dev/null +++ b/components/webcompat_reporter/browser/webcompat_report_uploader.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEBCOMPAT_REPORTER_BROWSER_WEBCOMPAT_REPORT_UPLOADER_H_ +#define BRAVE_COMPONENTS_WEBCOMPAT_REPORTER_BROWSER_WEBCOMPAT_REPORT_UPLOADER_H_ + +#include +#include + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "url/gurl.h" + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace brave { + +class WebcompatReportUploader { + public: + explicit WebcompatReportUploader( + scoped_refptr); + ~WebcompatReportUploader(); + + void SubmitReport(std::string report_domain); + + private: + std::unique_ptr simple_url_loader_; + scoped_refptr shared_url_loader_factory_; + void CreateAndStartURLLoader(const GURL& upload_url, + const std::string& post_data); + void OnSimpleURLLoaderComplete(std::unique_ptr response_body); + + DISALLOW_COPY_AND_ASSIGN(WebcompatReportUploader); +}; + +} // namespace brave + +#endif // BRAVE_COMPONENTS_WEBCOMPAT_REPORTER_BROWSER_WEBCOMPAT_REPORT_UPLOADER_H_ From bcb580a1e1b5553c6182926b3d5b748147dc5632 Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Thu, 12 Sep 2019 13:38:09 -0700 Subject: [PATCH 4/5] allow reporting webcompat issues through the Shields panel --- browser/extensions/BUILD.gn | 1 + browser/extensions/api/brave_shields_api.cc | 25 +++++++++++++++++++ browser/extensions/api/brave_shields_api.h | 11 +++++++- common/extensions/api/brave_shields.json | 11 ++++++++ .../_locales/en_US/messages.json | 8 ++++-- .../actions/shieldsPanelActions.ts | 6 +++++ .../background/api/shieldsAPI.ts | 7 ++++++ .../reducers/shieldsPanelReducer.ts | 11 +++++++- .../brave_extension/components/display.ts | 1 + .../components/structure/index.ts | 10 ++++---- .../constants/shieldsPanelTypes.ts | 1 + .../containers/advancedView/header.tsx | 10 ++++++-- .../containers/advancedView/index.tsx | 3 +++ .../containers/braveShields.tsx | 2 ++ .../containers/simpleView/header.tsx | 10 ++++++-- .../containers/simpleView/index.tsx | 3 +++ .../brave_extension/theme/shields-dark.ts | 6 ++--- .../types/actions/shieldsPanelActions.ts | 9 +++++++ .../types/constants/shieldsPanelTypes.ts | 1 + components/definitions/chromel.d.ts | 1 + 20 files changed, 121 insertions(+), 16 deletions(-) diff --git a/browser/extensions/BUILD.gn b/browser/extensions/BUILD.gn index bd17ad252a3c..9dc0197c6fe7 100644 --- a/browser/extensions/BUILD.gn +++ b/browser/extensions/BUILD.gn @@ -61,6 +61,7 @@ source_set("extensions") { deps = [ "//base", "//brave/app:brave_generated_resources_grit", + "//brave/browser/webcompat_reporter", "//brave/common", "//brave/common:pref_names", "//brave/common/extensions/api", diff --git a/browser/extensions/api/brave_shields_api.cc b/browser/extensions/api/brave_shields_api.cc index 5b5083ad6a0b..14777de13cea 100644 --- a/browser/extensions/api/brave_shields_api.cc +++ b/browser/extensions/api/brave_shields_api.cc @@ -11,6 +11,7 @@ #include "base/strings/string_number_conversions.h" #include "brave/browser/extensions/api/brave_action_api.h" +#include "brave/browser/webcompat_reporter/webcompat_reporter_dialog.h" #include "brave/common/extensions/api/brave_shields.h" #include "brave/common/extensions/extension_constants.h" #include "brave/components/brave_shields/browser/brave_shields_p3a.h" @@ -326,5 +327,29 @@ BraveShieldsOnShieldsPanelShownFunction::Run() { return RespondNow(NoArguments()); } +ExtensionFunction::ResponseAction BraveShieldsReportBrokenSiteFunction::Run() { + std::unique_ptr params( + brave_shields::ReportBrokenSite::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + // Get web contents for this tab + content::WebContents* contents = nullptr; + if (!ExtensionTabUtil::GetTabById( + params->tab_id, + Profile::FromBrowserContext(browser_context()), + false, + nullptr, + nullptr, + &contents, + nullptr)) { + return RespondNow(Error(tabs_constants::kTabNotFoundError, + base::NumberToString(params->tab_id))); + } + + OpenWebcompatReporterDialog(contents); + + return RespondNow(NoArguments()); +} + } // namespace api } // namespace extensions diff --git a/browser/extensions/api/brave_shields_api.h b/browser/extensions/api/brave_shields_api.h index 02b0c577dec5..017dda73446e 100644 --- a/browser/extensions/api/brave_shields_api.h +++ b/browser/extensions/api/brave_shields_api.h @@ -158,7 +158,6 @@ class BraveShieldsGetNoScriptControlTypeFunction : public ExtensionFunction { ResponseAction Run() override; }; - // Notifies the browser that the shields panel was shown to the user. class BraveShieldsOnShieldsPanelShownFunction : public ExtensionFunction { public: @@ -171,6 +170,16 @@ class BraveShieldsOnShieldsPanelShownFunction : public ExtensionFunction { ResponseAction Run() override; }; +class BraveShieldsReportBrokenSiteFunction : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("braveShields.reportBrokenSite", UNKNOWN) + + protected: + ~BraveShieldsReportBrokenSiteFunction() override {} + + ResponseAction Run() override; +}; + } // namespace api } // namespace extensions diff --git a/common/extensions/api/brave_shields.json b/common/extensions/api/brave_shields.json index ebf43e2ac497..2f57e398a9c1 100644 --- a/common/extensions/api/brave_shields.json +++ b/common/extensions/api/brave_shields.json @@ -325,6 +325,17 @@ "parameters": [] } ] + }, + { + "name": "reportBrokenSite", + "type": "function", + "description": "Bring up a modal for reporting a site broken by Shields to the Brave developers", + "parameters": [ + { + "name": "tabId", + "type": "integer" + } + ] } ] } diff --git a/components/brave_extension/extension/brave_extension/_locales/en_US/messages.json b/components/brave_extension/extension/brave_extension/_locales/en_US/messages.json index 15cedb5616ab..20f4837ec980 100644 --- a/components/brave_extension/extension/brave_extension/_locales/en_US/messages.json +++ b/components/brave_extension/extension/brave_extension/_locales/en_US/messages.json @@ -24,8 +24,12 @@ "description": "Message telling the user to disable shields if a site appears broken" }, "disabledMessage": { - "message": "You’re browsing this site without any privacy and security protections.", - "description": "Message telling the user that shields are disabled" + "message": "You’re browsing this site without Brave’s privacy and security protections. Does it not work right with Shields up?", + "description": "Message telling the user that shields are disabled, and prompting them towards reporting an issue if necessary" + }, + "reportBrokenSite": { + "message": "Report a broken site", + "description": "Message for the button allowing users to report a broken site to Brave developers" }, "itemsBlocked": { "message": "Items blocked", diff --git a/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts b/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts index 2c472745ebe9..b566c3247c9d 100644 --- a/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts +++ b/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts @@ -19,6 +19,12 @@ export const shieldsToggled: actions.ShieldsToggled = (setting = 'allow') => { } } +export const reportBrokenSite: actions.ReportBrokenSite = () => { + return { + type: types.REPORT_BROKEN_SITE + } +} + export const resourceBlocked: actions.ResourceBlocked = (details) => { return { type: types.RESOURCE_BLOCKED, diff --git a/components/brave_extension/extension/brave_extension/background/api/shieldsAPI.ts b/components/brave_extension/extension/brave_extension/background/api/shieldsAPI.ts index 2a9b9aafbf1b..b39824165496 100644 --- a/components/brave_extension/extension/brave_extension/background/api/shieldsAPI.ts +++ b/components/brave_extension/extension/brave_extension/background/api/shieldsAPI.ts @@ -163,6 +163,13 @@ export const setAllowScriptOriginsOnce = (origins: Array, tabId: number) }) }) +/** + * Open a prompt that allows the user to submit a report telling Brave that the current website is broken by Shields. + * @param {number} tabId ID of the tab whose contents are being reported + */ +export const reportBrokenSite = (tabId: number) => + chrome.braveShields.reportBrokenSite(tabId) + export type GetViewPreferencesData = { showAdvancedView: boolean } diff --git a/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts b/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts index e89f0f460f18..c0269e98a179 100644 --- a/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts +++ b/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts @@ -29,7 +29,8 @@ import { toggleShieldsValue, requestShieldPanelData, setAllowScriptOriginsOnce, - onShieldsPanelShown + onShieldsPanelShown, + reportBrokenSite } from '../api/shieldsAPI' import { reloadTab } from '../api/tabsAPI' import { applySiteFilters } from '../api/cosmeticFilterAPI' @@ -127,6 +128,14 @@ export default function shieldsPanelReducer ( .updateTabShieldsData(state, tabId, { braveShields: action.setting }) break } + case shieldsPanelTypes.REPORT_BROKEN_SITE: { + chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { + if (tabs[0] && tabs[0].id) { + reportBrokenSite(tabs[0].id) + } + }) + break + } case shieldsPanelTypes.HTTPS_EVERYWHERE_TOGGLED: { const tabData = shieldsPanelState.getActiveTabData(state) if (!tabData) { diff --git a/components/brave_extension/extension/brave_extension/components/display.ts b/components/brave_extension/extension/brave_extension/components/display.ts index 7e37fc03ecd1..b3e623c2ef90 100644 --- a/components/brave_extension/extension/brave_extension/components/display.ts +++ b/components/brave_extension/extension/brave_extension/components/display.ts @@ -191,6 +191,7 @@ export const DisabledContentText = styled<{}, 'div'>('div')` font-size: 12px; font-weight: normal; line-height: 18px; + text-align: center; ` /** diff --git a/components/brave_extension/extension/brave_extension/components/structure/index.ts b/components/brave_extension/extension/brave_extension/components/structure/index.ts index 4573caddc7f2..c738ac0511bc 100644 --- a/components/brave_extension/extension/brave_extension/components/structure/index.ts +++ b/components/brave_extension/extension/brave_extension/components/structure/index.ts @@ -428,11 +428,11 @@ export const BlockedListFooterWithOptions = styled<{}, 'footer'>('footer')` export const DisabledContentView = styled<{}, 'section'>('section')` box-sizing: border-box; display: grid; - grid-template-columns: 2fr 5fr; - grid-gap: 4px; - align-items: center; - max-width: 80%; - margin: 5px auto 8px; + grid-template-rows: auto auto; + grid-gap: 12px; + justify-items: center; + max-width: 70%; + margin: 12px auto 0; ` /** diff --git a/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts b/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts index a4f5ab93a8ba..0b1ee008ef0d 100644 --- a/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts +++ b/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts @@ -4,6 +4,7 @@ export const SHIELDS_PANEL_DATA_UPDATED = 'SHIELDS_PANEL_DATA_UPDATED' export const SHIELDS_TOGGLED = 'SHIELDS_TOGGLED' +export const REPORT_BROKEN_SITE = 'REPORT_BROKEN_SITE' export const RESOURCE_BLOCKED = 'RESOURCE_BLOCKED' export const BLOCK_ADS_TRACKERS = 'BLOCK_ADS_TRACKERS' export const CONTROLS_TOGGLED = 'CONTROLS_TOGGLED' diff --git a/components/brave_extension/extension/brave_extension/containers/advancedView/header.tsx b/components/brave_extension/extension/brave_extension/containers/advancedView/header.tsx index 38997ead1cb3..eb93af95c57d 100644 --- a/components/brave_extension/extension/brave_extension/containers/advancedView/header.tsx +++ b/components/brave_extension/extension/brave_extension/containers/advancedView/header.tsx @@ -19,7 +19,7 @@ import { TotalBlockedStatsNumber, TotalBlockedStatsText, DisabledContentView, - ShieldIcon, + ShieldsButton, DisabledContentText, Toggle } from '../../components' @@ -41,6 +41,7 @@ interface CommonProps { hostname: string isBlockedListOpen: boolean shieldsToggled: ShieldsToggled + reportBrokenSite: () => void } interface BlockedItemsProps { @@ -75,6 +76,11 @@ export default class Header extends React.PureComponent { this.props.shieldsToggled(shieldsOption) } + onReportBrokenSite = () => { + this.props.reportBrokenSite() + window.close() + } + render () { const { enabled, favicon, hostname, isBlockedListOpen } = this.props return ( @@ -109,8 +115,8 @@ export default class Header extends React.PureComponent { ) : ( -
{getLocale('disabledMessage')} +
) } diff --git a/components/brave_extension/extension/brave_extension/containers/advancedView/index.tsx b/components/brave_extension/extension/brave_extension/containers/advancedView/index.tsx index 806d006db346..187f83b70c82 100644 --- a/components/brave_extension/extension/brave_extension/containers/advancedView/index.tsx +++ b/components/brave_extension/extension/brave_extension/containers/advancedView/index.tsx @@ -22,6 +22,7 @@ import { Tab, PersistentData } from '../../types/state/shieldsPannelState' import { isShieldsEnabled, getFavicon } from '../../helpers/shieldsUtils' import { ShieldsToggled, + ReportBrokenSite, BlockAdsTrackers, HttpsEverywhereToggled, BlockJavaScript, @@ -38,6 +39,7 @@ import { interface Props { actions: { shieldsToggled: ShieldsToggled + reportBrokenSite: ReportBrokenSite blockAdsTrackers: BlockAdsTrackers httpsEverywhereToggled: HttpsEverywhereToggled blockJavaScript: BlockJavaScript @@ -104,6 +106,7 @@ export default class Shields extends React.PureComponent { scriptsBlocked={shieldsPanelTabData.javascriptBlocked} fingerprintingBlocked={shieldsPanelTabData.fingerprintingBlocked} shieldsToggled={actions.shieldsToggled} + reportBrokenSite={actions.reportBrokenSite} /> { this.isShieldsEnabled && ( diff --git a/components/brave_extension/extension/brave_extension/containers/braveShields.tsx b/components/brave_extension/extension/brave_extension/containers/braveShields.tsx index a3acaf12d792..7043dd07375b 100644 --- a/components/brave_extension/extension/brave_extension/containers/braveShields.tsx +++ b/components/brave_extension/extension/brave_extension/containers/braveShields.tsx @@ -19,6 +19,7 @@ import * as shieldsAPI from '../background/api/shieldsAPI' import { Tab, PersistentData } from '../types/state/shieldsPannelState' import { ShieldsToggled, + ReportBrokenSite, BlockAdsTrackers, HttpsEverywhereToggled, BlockJavaScript, @@ -36,6 +37,7 @@ import { interface Props { actions: { shieldsToggled: ShieldsToggled + reportBrokenSite: ReportBrokenSite blockAdsTrackers: BlockAdsTrackers httpsEverywhereToggled: HttpsEverywhereToggled blockJavaScript: BlockJavaScript diff --git a/components/brave_extension/extension/brave_extension/containers/simpleView/header.tsx b/components/brave_extension/extension/brave_extension/containers/simpleView/header.tsx index 7de9cb3dfab2..b2802a955a17 100644 --- a/components/brave_extension/extension/brave_extension/containers/simpleView/header.tsx +++ b/components/brave_extension/extension/brave_extension/containers/simpleView/header.tsx @@ -20,7 +20,7 @@ import { TotalBlockedStatsNumber, TotalBlockedStatsText, DisabledContentView, - ShieldIcon, + ShieldsButton, DisabledContentText, Toggle } from '../../components' @@ -42,6 +42,7 @@ interface CommonProps { hostname: string shieldsToggled: ShieldsToggled toggleReadOnlyView: () => void + reportBrokenSite: () => void } interface BlockedItemsProps { @@ -71,6 +72,11 @@ export default class Header extends React.PureComponent { this.props.shieldsToggled(shieldsOption) } + onReportBrokenSite = () => { + this.props.reportBrokenSite() + window.close() + } + render () { const { enabled, favicon, hostname, toggleReadOnlyView } = this.props return ( @@ -106,8 +112,8 @@ export default class Header extends React.PureComponent { ) : ( -
{getLocale('disabledMessage')} +
) } diff --git a/components/brave_extension/extension/brave_extension/containers/simpleView/index.tsx b/components/brave_extension/extension/brave_extension/containers/simpleView/index.tsx index 51c4b281ff01..9306f3f280ae 100644 --- a/components/brave_extension/extension/brave_extension/containers/simpleView/index.tsx +++ b/components/brave_extension/extension/brave_extension/containers/simpleView/index.tsx @@ -13,6 +13,7 @@ import Footer from './footer' import { ShieldsToggled, + ReportBrokenSite, BlockAdsTrackers, HttpsEverywhereToggled, BlockJavaScript, @@ -33,6 +34,7 @@ import { getFavicon, isShieldsEnabled } from '../../helpers/shieldsUtils' interface Props { actions: { shieldsToggled: ShieldsToggled + reportBrokenSite: ReportBrokenSite blockAdsTrackers: BlockAdsTrackers httpsEverywhereToggled: HttpsEverywhereToggled blockJavaScript: BlockJavaScript @@ -77,6 +79,7 @@ export default class ShieldsSimpleView extends React.PureComponent { fingerprintingBlocked={shieldsPanelTabData.fingerprintingBlocked} shieldsToggled={actions.shieldsToggled} toggleReadOnlyView={toggleReadOnlyView} + reportBrokenSite={actions.reportBrokenSite} />