From 90e475bef8a11c6beeae2930410bdb686d6a0676 Mon Sep 17 00:00:00 2001 From: Simon Hong Date: Wed, 21 Jul 2021 22:05:55 +0900 Subject: [PATCH] Implement crash reporting permission ask dialog fix https://github.com/brave/brave-browser/issues/1841 Launch crash reporting permission ask dialog on startup after crash. Launch tab restore dialog after permission ask dialog is closed. By overriding, ShowIfNotOffTheRecordProfileBrave() is called instead of ShowIfNotOffTheRecordProfile(). ShowIfNotOffTheRecordProfileBrave() will launch crash reporting permission ask dialog and then tab restore dialog is launched after permission ask dialog is closed. --- app/brave_generated_resources.grd | 22 ++ app/vector_icons/BUILD.gn | 1 + app/vector_icons/brave_sad.icon | 50 ++++ browser/metrics/{test => }/BUILD.gn | 22 +- .../metrics/brave_metrics_service_accessor.cc | 11 + .../metrics/brave_metrics_service_accessor.h | 21 ++ browser/metrics/metrics_reporting_util.cc | 12 + browser/metrics/metrics_reporting_util.h | 1 + .../metrics_reporting_util_unittest.cc | 27 ++ browser/sources.gni | 2 + browser/themes/theme_properties.cc | 4 + browser/themes/theme_properties.h | 1 + browser/ui/BUILD.gn | 4 + browser/ui/browser_dialogs.h | 2 + browser/ui/session_crashed_bubble_brave.cc | 20 ++ ...eport_permission_ask_dialog_browsertest.cc | 36 +++ ...crash_report_permission_ask_dialog_view.cc | 261 ++++++++++++++++++ .../crash_report_permission_ask_dialog_view.h | 41 +++ .../browser/ui/session_crashed_bubble.h | 17 ++ .../startup/startup_browser_creator_impl.cc | 3 + test/BUILD.gn | 3 +- 21 files changed, 551 insertions(+), 10 deletions(-) create mode 100644 app/vector_icons/brave_sad.icon rename browser/metrics/{test => }/BUILD.gn (70%) create mode 100644 browser/metrics/brave_metrics_service_accessor.cc create mode 100644 browser/metrics/brave_metrics_service_accessor.h create mode 100644 browser/metrics/metrics_reporting_util_unittest.cc create mode 100644 browser/ui/session_crashed_bubble_brave.cc create mode 100644 browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc create mode 100644 browser/ui/views/crash_report_permission_ask_dialog_view.cc create mode 100644 browser/ui/views/crash_report_permission_ask_dialog_view.h create mode 100644 chromium_src/chrome/browser/ui/session_crashed_bubble.h diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd index b1e956d8a132..02ef1ce64449 100644 --- a/app/brave_generated_resources.grd +++ b/app/brave_generated_resources.grd @@ -1129,6 +1129,28 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U Not now + + + Allow + + + Block + + + Send crash reports automatically so Brave can prevent this issue from happening again? + + + $1Brave Browser quit unexpectedly. + + + Brave Browser + + + You can change $1this setting again at any time. + + + this setting + diff --git a/app/vector_icons/BUILD.gn b/app/vector_icons/BUILD.gn index c0179eea09b8..09542b3decdf 100644 --- a/app/vector_icons/BUILD.gn +++ b/app/vector_icons/BUILD.gn @@ -14,6 +14,7 @@ aggregate_vector_icons("brave_vector_icons") { "brave_ads_close_button.icon", "brave_ads_dark_mode_info_button.icon", "brave_ads_light_mode_info_button.icon", + "brave_sad.icon", "download_unlock.icon", "open_in_ipfs.icon", "open_in_tor.icon", diff --git a/app/vector_icons/brave_sad.icon b/app/vector_icons/brave_sad.icon new file mode 100644 index 000000000000..90a92b0af891 --- /dev/null +++ b/app/vector_icons/brave_sad.icon @@ -0,0 +1,50 @@ +// Copyright (c) 2021 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/. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 22, 23, +H_LINE_TO, 2, +R_CUBIC_TO, -1.1f, 0, -2, -0.9f, -2, -2, +V_LINE_TO, 3, +R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2, +R_H_LINE_TO, 20, +R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2, +R_V_LINE_TO, 18, +R_CUBIC_TO, 0, 1.1f, -0.9f, 2, -2, 2, +CLOSE, +R_MOVE_TO, 0, -2, +R_LINE_TO, 0, -14, +H_LINE_TO, 2, +R_V_LINE_TO, 14, +R_H_LINE_TO, 20, +CLOSE, +MOVE_TO, 2, 3, +R_V_LINE_TO, 2, +R_H_LINE_TO, 20, +V_LINE_TO, 3, +H_LINE_TO, 2, +CLOSE, +R_MOVE_TO, 6.64f, 14.66f, +R_ARC_TO, 0.99f, 0.99f, 0, 0, 1, -1.41f, -0.13f, +R_ARC_TO, 1.03f, 1.03f, 0, 0, 1, 0.13f, -1.43f, +R_CUBIC_TO, 1.5f, -1.27f, 3.05f, -1.92f, 4.64f, -1.92f, +R_CUBIC_TO, 1.59f, 0, 3.14f, 0.66f, 4.64f, 1.93f, +R_CUBIC_TO, 0.42f, 0.36f, 0.48f, 1, 0.13f, 1.43f, +R_ARC_TO, 0.99f, 0.99f, 0, 0, 1, -1.41f, 0.13f, +CUBIC_TO, 14.2f, 16.67f, 13.08f, 16.2f, 12, 16.2f, +R_CUBIC_TO, -1.08f, 0, -2.2f, 0.47f, -3.36f, 1.46f, +CLOSE, +MOVE_TO, 9, 12.14f, +R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1.01f, +R_CUBIC_TO, 0, -0.56f, -0.45f, -1.01f, -1, -1.01f, +R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1.01f, +R_CUBIC_TO, 0, 0.56f, 0.45f, 1.02f, 1, 1.02f, +CLOSE, +R_MOVE_TO, 6, 0, +R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1.01f, +R_CUBIC_TO, 0, -0.56f, -0.45f, -1.01f, -1, -1.01f, +R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1.01f, +R_CUBIC_TO, 0, 0.56f, 0.45f, 1.02f, 1, 1.02f, +CLOSE diff --git a/browser/metrics/test/BUILD.gn b/browser/metrics/BUILD.gn similarity index 70% rename from browser/metrics/test/BUILD.gn rename to browser/metrics/BUILD.gn index a7a597606628..94213ff07cd9 100644 --- a/browser/metrics/test/BUILD.gn +++ b/browser/metrics/BUILD.gn @@ -10,19 +10,23 @@ import("//testing/test.gni") source_set("brave_metrics_unit_tests") { testonly = true + + sources = [ "metrics_reporting_util_unittest.cc" ] + deps = [ + "//base/test:test_support", + "//brave/browser", + "//chrome/browser", + "//chrome/test:test_support", + "//content/test:test_support", + ] + if (is_linux) { - sources = - [ "//brave/browser/metrics/metrics_reporting_util_unittest_linux.cc" ] + sources += [ "metrics_reporting_util_unittest_linux.cc" ] + configs += [ "//brave/build/linux:linux_channel_names" ] - deps = [ - "//base/test:test_support", - "//brave/browser", - "//chrome/browser:browser", + deps += [ "//chrome/common:channel_info", "//components/version_info:channel", - "//content/test:test_support", ] - - configs += [ "//brave/build/linux:linux_channel_names" ] } } diff --git a/browser/metrics/brave_metrics_service_accessor.cc b/browser/metrics/brave_metrics_service_accessor.cc new file mode 100644 index 000000000000..45623d68fcf1 --- /dev/null +++ b/browser/metrics/brave_metrics_service_accessor.cc @@ -0,0 +1,11 @@ +/* Copyright (c) 2021 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/metrics/brave_metrics_service_accessor.h" +#include "chrome/browser/browser_process.h" + +bool BraveMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled() { + return IsMetricsReportingEnabled(g_browser_process->local_state()); +} diff --git a/browser/metrics/brave_metrics_service_accessor.h b/browser/metrics/brave_metrics_service_accessor.h new file mode 100644 index 000000000000..731b65fd81e7 --- /dev/null +++ b/browser/metrics/brave_metrics_service_accessor.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2021 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_METRICS_BRAVE_METRICS_SERVICE_ACCESSOR_H_ +#define BRAVE_BROWSER_METRICS_BRAVE_METRICS_SERVICE_ACCESSOR_H_ + +#include "components/metrics/metrics_service_accessor.h" + +// This class limits and documents access to metrics service helper methods. +// Since these methods are private, each user has to be explicitly declared +// as a 'friend' below. +class BraveMetricsServiceAccessor : public metrics::MetricsServiceAccessor { + private: + friend bool ShouldShowCrashReportPermissionAskDialog(); + + static bool IsMetricsAndCrashReportingEnabled(); +}; + +#endif // BRAVE_BROWSER_METRICS_BRAVE_METRICS_SERVICE_ACCESSOR_H_ diff --git a/browser/metrics/metrics_reporting_util.cc b/browser/metrics/metrics_reporting_util.cc index e272a6f08e42..a3c633a056ff 100644 --- a/browser/metrics/metrics_reporting_util.cc +++ b/browser/metrics/metrics_reporting_util.cc @@ -7,6 +7,8 @@ #include "base/logging.h" #include "base/notreached.h" +#include "brave/browser/metrics/brave_metrics_service_accessor.h" +#include "chrome/browser/metrics/metrics_reporting_state.h" #include "chrome/common/channel_info.h" #include "components/version_info/channel.h" @@ -25,3 +27,13 @@ bool GetDefaultPrefValueForMetricsReporting() { return false; } } + +bool ShouldShowCrashReportPermissionAskDialog() { + if (IsMetricsReportingPolicyManaged()) + return false; + + if (BraveMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled()) + return false; + + return true; +} diff --git a/browser/metrics/metrics_reporting_util.h b/browser/metrics/metrics_reporting_util.h index 31805a0eed3c..3d542f7e6eb9 100644 --- a/browser/metrics/metrics_reporting_util.h +++ b/browser/metrics/metrics_reporting_util.h @@ -7,5 +7,6 @@ #define BRAVE_BROWSER_METRICS_METRICS_REPORTING_UTIL_H_ bool GetDefaultPrefValueForMetricsReporting(); +bool ShouldShowCrashReportPermissionAskDialog(); #endif // BRAVE_BROWSER_METRICS_METRICS_REPORTING_UTIL_H_ diff --git a/browser/metrics/metrics_reporting_util_unittest.cc b/browser/metrics/metrics_reporting_util_unittest.cc new file mode 100644 index 000000000000..bccd4bca9512 --- /dev/null +++ b/browser/metrics/metrics_reporting_util_unittest.cc @@ -0,0 +1,27 @@ +/* Copyright (c) 2021 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 + +#include "brave/browser/metrics/metrics_reporting_util.h" +#include "chrome/test/base/scoped_testing_local_state.h" +#include "chrome/test/base/testing_browser_process.h" +#include "components/metrics/metrics_pref_names.h" +#include "components/prefs/pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(MetricsUtilTest, CrashReportPermissionAskDialogTest) { + std::unique_ptr local_state = + std::make_unique( + TestingBrowserProcess::GetGlobal()); + + g_browser_process->local_state()->SetBoolean( + metrics::prefs::kMetricsReportingEnabled, false); + EXPECT_TRUE(ShouldShowCrashReportPermissionAskDialog()); + + g_browser_process->local_state()->SetBoolean( + metrics::prefs::kMetricsReportingEnabled, true); + EXPECT_FALSE(ShouldShowCrashReportPermissionAskDialog()); +} diff --git a/browser/sources.gni b/browser/sources.gni index dfbd5db7a02a..d7b547ee4e4b 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -80,6 +80,8 @@ brave_chrome_browser_sources = [ "//brave/browser/browser_context_keyed_service_factories.h", "//brave/browser/geolocation/brave_geolocation_permission_context_delegate.cc", "//brave/browser/geolocation/brave_geolocation_permission_context_delegate.h", + "//brave/browser/metrics/brave_metrics_service_accessor.cc", + "//brave/browser/metrics/brave_metrics_service_accessor.h", "//brave/browser/metrics/metrics_reporting_util.cc", "//brave/browser/metrics/metrics_reporting_util.h", "//brave/browser/update_util.cc", diff --git a/browser/themes/theme_properties.cc b/browser/themes/theme_properties.cc index 50d2ab31c746..bd298c15a877 100644 --- a/browser/themes/theme_properties.cc +++ b/browser/themes/theme_properties.cc @@ -44,6 +44,8 @@ absl::optional MaybeGetDefaultColorForBraveLightUi(int id) { return kLightToolbarIcon; case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON_INACTIVE: return color_utils::AlphaBlend(kLightToolbarIcon, kLightToolbar, 0.3f); + case BraveThemeProperties::COLOR_ICON_BASE: + return SkColorSetRGB(0x49, 0x50, 0x57); #if BUILDFLAG(ENABLE_SIDEBAR) case BraveThemeProperties::COLOR_SIDEBAR_BACKGROUND: return SkColorSetRGB(0xF3, 0xF3, 0xF5); @@ -128,6 +130,8 @@ absl::optional MaybeGetDefaultColorForBraveDarkUi(int id) { return kDarkToolbarIcon; case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON_INACTIVE: return color_utils::AlphaBlend(kDarkToolbarIcon, kDarkToolbar, 0.3f); + case BraveThemeProperties::COLOR_ICON_BASE: + return SkColorSetRGB(0xC2, 0xC4, 0xCF); #if BUILDFLAG(ENABLE_SIDEBAR) case BraveThemeProperties::COLOR_SIDEBAR_BACKGROUND: return kDarkToolbar; diff --git a/browser/themes/theme_properties.h b/browser/themes/theme_properties.h index d7da7c54242c..bb3637dbfc69 100644 --- a/browser/themes/theme_properties.h +++ b/browser/themes/theme_properties.h @@ -25,6 +25,7 @@ enum TestProperty { enum ThemeProperties { BRAVE_THEME_PROPERTIES_START = 10000, COLOR_BOOKMARK_BAR_INSTRUCTIONS_TEXT = BRAVE_THEME_PROPERTIES_START, + COLOR_ICON_BASE, #if BUILDFLAG(ENABLE_SIDEBAR) COLOR_SIDEBAR_ADD_BUTTON_DISABLED, COLOR_SIDEBAR_BACKGROUND, diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index e1d9f8c426ac..dac1b711951b 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -80,6 +80,7 @@ source_set("ui") { "content_settings/brave_content_setting_image_models.h", "omnibox/brave_omnibox_client_impl.cc", "omnibox/brave_omnibox_client_impl.h", + "session_crashed_bubble_brave.cc", "startup/default_brave_browser_prompt.cc", "startup/default_brave_browser_prompt.h", "toolbar/brave_app_menu_model.cc", @@ -132,6 +133,8 @@ source_set("ui") { "views/brave_default_browser_dialog_view.h", "views/brave_layout_provider.cc", "views/brave_layout_provider.h", + "views/crash_report_permission_ask_dialog_view.cc", + "views/crash_report_permission_ask_dialog_view.h", "views/download/brave_download_item_view.cc", "views/download/brave_download_item_view.h", "views/frame/brave_browser_view.cc", @@ -542,6 +545,7 @@ source_set("ui") { if (toolkit_views) { deps += [ + "//components/constrained_window", "//ui/events", "//ui/views", ] diff --git a/browser/ui/browser_dialogs.h b/browser/ui/browser_dialogs.h index 8f34abdc373a..b93e34561b2b 100644 --- a/browser/ui/browser_dialogs.h +++ b/browser/ui/browser_dialogs.h @@ -11,6 +11,8 @@ class Browser; namespace brave { void ShowDefaultBrowserDialog(Browser* browser); +// Tab restore dialog will be launched after ask dialog is closed. +void ShowCrashReportPermissionAskDialog(Browser* browser); } // namespace brave diff --git a/browser/ui/session_crashed_bubble_brave.cc b/browser/ui/session_crashed_bubble_brave.cc new file mode 100644 index 000000000000..49f9a6e4a816 --- /dev/null +++ b/browser/ui/session_crashed_bubble_brave.cc @@ -0,0 +1,20 @@ +/* Copyright (c) 2021 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/metrics/metrics_reporting_util.h" +#include "brave/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/session_crashed_bubble.h" + +// static +void SessionCrashedBubble::ShowIfNotOffTheRecordProfileBrave(Browser* browser) { + // If crash report permission ask dialog is launched, tab restore bubble will + // be shown after closing aks dialog. + if (ShouldShowCrashReportPermissionAskDialog()) { + brave::ShowCrashReportPermissionAskDialog(browser); + return; + } + + ShowIfNotOffTheRecordProfile(browser); +} diff --git a/browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc b/browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc new file mode 100644 index 000000000000..cb7fcf38ab3b --- /dev/null +++ b/browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc @@ -0,0 +1,36 @@ +/* Copyright (c) 2021 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/metrics/metrics_reporting_util.h" +#include "brave/browser/ui/brave_browser.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/session_crashed_bubble.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "components/metrics/metrics_pref_names.h" +#include "components/prefs/pref_service.h" +#include "content/public/test/browser_test.h" + +class CrashReportPermissionAskDialogTest : public DialogBrowserTest { + public: + CrashReportPermissionAskDialogTest() = default; + ~CrashReportPermissionAskDialogTest() override = default; + + // TestBrowserUi: + void ShowUi(const std::string& name) override { + SessionCrashedBubble::ShowIfNotOffTheRecordProfileBrave(browser()); + } +}; + +IN_PROC_BROWSER_TEST_F(CrashReportPermissionAskDialogTest, InvokeUi_Dialog) { + // When reporting is disabled, crash report permission ask dialog is launched. + g_browser_process->local_state()->SetBoolean( + metrics::prefs::kMetricsReportingEnabled, false); + ShowAndVerifyUi(); + + // When reporting is enabled, tab restore dialog is launched. + g_browser_process->local_state()->SetBoolean( + metrics::prefs::kMetricsReportingEnabled, true); + ShowAndVerifyUi(); +} diff --git a/browser/ui/views/crash_report_permission_ask_dialog_view.cc b/browser/ui/views/crash_report_permission_ask_dialog_view.cc new file mode 100644 index 000000000000..22c925a637b2 --- /dev/null +++ b/browser/ui/views/crash_report_permission_ask_dialog_view.cc @@ -0,0 +1,261 @@ +/* Copyright (c) 2021 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/views/crash_report_permission_ask_dialog_view.h" + +#include + +#include "base/bind.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "brave/app/vector_icons/vector_icons.h" +#include "brave/browser/themes/theme_properties.h" +#include "brave/grit/brave_generated_resources.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/metrics/metrics_reporting_state.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chrome_pages.h" +#include "chrome/browser/ui/session_crashed_bubble.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/common/webui_url_constants.h" +#include "components/constrained_window/constrained_window_views.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/models/image_model.h" +#include "ui/base/theme_provider.h" +#include "ui/views/background.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/styled_label.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/layout/layout_provider.h" + +namespace brave { + +void ShowCrashReportPermissionAskDialog(Browser* browser) { + CrashReportPermissionAskDialogView::Show(browser); +} + +} // namespace brave + +namespace { + +void ScheduleSessionCrashedBubble() { + // It's ok to use lastly used browser because there will be only one when + // this launched after un-cleaned exit. + if (auto* browser = BrowserList::GetInstance()->GetLastActive()) + SessionCrashedBubble::ShowIfNotOffTheRecordProfile(browser); +} + +gfx::FontList GetFont(int font_size, gfx::Font::Weight weight) { + gfx::FontList font_list; + return font_list.DeriveWithSizeDelta(font_size - font_list.GetFontSize()) + .DeriveWithWeight(weight); +} + +void OpenSettingPage() { + if (auto* browser = BrowserList::GetInstance()->GetLastActive()) + chrome::ShowSettingsSubPageForProfile(browser->profile(), + chrome::kPrivacySubPage); +} + +} // namespace + +// static +void CrashReportPermissionAskDialogView::Show(Browser* browser) { + constrained_window::CreateBrowserModalDialogViews( + new CrashReportPermissionAskDialogView(browser), + browser->window()->GetNativeWindow()) + ->Show(); +} + +CrashReportPermissionAskDialogView::CrashReportPermissionAskDialogView( + Browser* browser) { + set_should_ignore_snapping(true); + + SetButtonLabel(ui::DIALOG_BUTTON_OK, + l10n_util::GetStringUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_OK_BUTTON_LABEL)); + SetButtonLabel( + ui::DIALOG_BUTTON_CANCEL, + l10n_util::GetStringUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_CANCEL_BUTTON_LABEL)); + SetAcceptCallback( + base::BindOnce(&CrashReportPermissionAskDialogView::OnAcceptButtonClicked, + base::Unretained(this))); + RegisterWindowClosingCallback( + base::BindOnce(&CrashReportPermissionAskDialogView::OnWindowClosing, + base::Unretained(this))); + + CreateChildViews(BrowserView::GetBrowserViewForBrowser(browser)->GetWidget()); +} + +CrashReportPermissionAskDialogView::~CrashReportPermissionAskDialogView() = + default; + +void CrashReportPermissionAskDialogView::CreateChildViews( + views::Widget* parent) { + constexpr int kPadding = 24; + constexpr int kChildSpacing = 16; + constexpr int kIconSize = 24; + + SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kVertical, gfx::Insets(kPadding), + kChildSpacing)); + + // Construct header text area + auto* header = AddChildView(std::make_unique()); + header->SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), + kChildSpacing)); + + constexpr SkColor kDefaultSadImageColor = SkColorSetRGB(0x49, 0x50, 0x57); + auto* header_image = + header->AddChildView(std::make_unique()); + header_image->SetImageSize(gfx::Size(kIconSize, kIconSize)); + SkColor header_image_color = kDefaultSadImageColor; + if (auto* theme_provider = parent->GetThemeProvider()) { + header_image_color = + theme_provider->GetColor(BraveThemeProperties::COLOR_ICON_BASE); + } + header_image->SetImage(ui::ImageModel::FromVectorIcon( + kBraveSadIcon, header_image_color, kIconSize)); + + const std::u16string header_browser_name = l10n_util::GetStringUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_HEADER_TEXT_BROWSER_NAME_PART); + size_t offset; + const std::u16string header_text = l10n_util::GetStringFUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_HEADER_TEXT, header_browser_name, + &offset); + auto* header_label = + header->AddChildView(std::make_unique()); + header_label->SetText(header_text); + + views::StyledLabel::RangeStyleInfo name_style; + name_style.custom_font = GetFont(14, gfx::Font::Weight::SEMIBOLD); + header_label->AddStyleRange( + gfx::Range(offset, offset + header_browser_name.length()), name_style); + + views::StyledLabel::RangeStyleInfo default_style; + default_style.custom_font = GetFont(14, gfx::Font::Weight::NORMAL); + + header_label->AddStyleRange( + gfx::Range(offset + header_browser_name.length(), header_text.length()), + default_style); + // If browser name is located in the middle of full text, apply default style + // all other area. + if (offset != 0) + header_label->AddStyleRange(gfx::Range(0, offset), default_style); + + // Construct contents text area + auto* contents = AddChildView(std::make_unique()); + contents->SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kHorizontal, + gfx::Insets{0, kPadding + kChildSpacing, 0, 0})); + constexpr int kContentsTextFontSize = 13; + auto* contents_label = contents->AddChildView(std::make_unique( + l10n_util::GetStringUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_CONTENT_TEXT), + views::Label::CustomFont{ + GetFont(kContentsTextFontSize, gfx::Font::Weight::NORMAL)})); + contents_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + contents_label->SetMultiLine(true); + constexpr int kContentsLabelMaxWidth = 350; + contents_label->SetMaximumWidth(kContentsLabelMaxWidth); + + // Construct footnote text area + constexpr int kFootnoteVerticalPadding = 16; + auto* footnote = SetFootnoteView(std::make_unique()); + auto* footnote_layout = + footnote->SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kHorizontal, + gfx::Insets{kFootnoteVerticalPadding, 0})); + footnote_layout->set_main_axis_alignment( + views::BoxLayout::MainAxisAlignment::kCenter); + footnote->SetBackground(views::CreateThemedSolidBackground( + footnote, ui::NativeTheme::kColorId_DialogBackground)); + + const std::u16string setting_text = l10n_util::GetStringUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_FOOTNOTE_TEXT_SETTING_PART); + const std::u16string footnote_text = l10n_util::GetStringFUTF16( + IDS_CRASH_REPORT_PERMISSION_ASK_DIALOG_FOOTNOTE_TEXT, setting_text, + &offset); + auto* footnote_label = + footnote->AddChildView(std::make_unique()); + footnote_label->SetHorizontalAlignment(gfx::ALIGN_CENTER); + footnote_label->SetText(footnote_text); + + views::StyledLabel::RangeStyleInfo setting_style = + views::StyledLabel::RangeStyleInfo::CreateForLink( + base::BindRepeating(OpenSettingPage)); + footnote_label->AddStyleRange( + gfx::Range(offset, offset + setting_text.length()), setting_style); + + views::StyledLabel::RangeStyleInfo footnote_default_style; + constexpr int kFootnoteFontSize = 12; + footnote_default_style.custom_font = + GetFont(kFootnoteFontSize, gfx::Font::Weight::NORMAL); + + if (offset != 0) + footnote_label->AddStyleRange(gfx::Range(0, offset), + footnote_default_style); + + if (offset + setting_text.length() != footnote_text.length()) + footnote_label->AddStyleRange( + gfx::Range(offset + setting_text.length(), footnote_text.length()), + footnote_default_style); +} + +std::unique_ptr +CrashReportPermissionAskDialogView::CreateNonClientFrameView( + views::Widget* widget) { + if (!use_custom_frame()) + return DialogDelegateView::CreateNonClientFrameView(widget); + + views::LayoutProvider* provider = views::LayoutProvider::Get(); + auto frame = std::make_unique( + provider->GetInsetsMetric(views::INSETS_DIALOG_TITLE), gfx::Insets()); + + const views::BubbleBorder::Shadow kShadow = + views::BubbleBorder::DIALOG_SHADOW; + std::unique_ptr border = + std::make_unique(views::BubbleBorder::FLOAT, kShadow, + gfx::kPlaceholderColor); + border->set_use_theme_background_color(true); + constexpr int kCornerRadius = 16; + border->SetCornerRadius(kCornerRadius); + frame->SetFootnoteView(DisownFootnoteView()); + frame->SetBubbleBorder(std::move(border)); + return frame; +} + +ui::ModalType CrashReportPermissionAskDialogView::GetModalType() const { + return ui::MODAL_TYPE_WINDOW; +} + +bool CrashReportPermissionAskDialogView::ShouldShowCloseButton() const { + return false; +} + +bool CrashReportPermissionAskDialogView::ShouldShowWindowTitle() const { + return false; +} + +void CrashReportPermissionAskDialogView::OnDialogInitialized() { + SetButtonRowInsets(gfx::Insets(0, 0, 18, 24)); +} + +void CrashReportPermissionAskDialogView::OnAcceptButtonClicked() { + // Enable crash reporting. + ChangeMetricsReportingState(true); +} + +void CrashReportPermissionAskDialogView::OnWindowClosing() { + // On macOS, this dialog is not destroyed properly when session crashed bubble + // is launched directly. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&ScheduleSessionCrashedBubble)); +} diff --git a/browser/ui/views/crash_report_permission_ask_dialog_view.h b/browser/ui/views/crash_report_permission_ask_dialog_view.h new file mode 100644 index 000000000000..03ea080ecbd8 --- /dev/null +++ b/browser/ui/views/crash_report_permission_ask_dialog_view.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2021 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_VIEWS_CRASH_REPORT_PERMISSION_ASK_DIALOG_VIEW_H_ +#define BRAVE_BROWSER_UI_VIEWS_CRASH_REPORT_PERMISSION_ASK_DIALOG_VIEW_H_ + +#include + +#include "ui/views/window/dialog_delegate.h" + +class Browser; + +class CrashReportPermissionAskDialogView : public views::DialogDelegateView { + public: + static void Show(Browser* browser); + + private: + explicit CrashReportPermissionAskDialogView(Browser* browser); + ~CrashReportPermissionAskDialogView() override; + + CrashReportPermissionAskDialogView( + const CrashReportPermissionAskDialogView&) = delete; + CrashReportPermissionAskDialogView& operator=( + const CrashReportPermissionAskDialogView&) = delete; + + // views::DialogDelegateView overrides: + std::unique_ptr CreateNonClientFrameView( + views::Widget* widget) override; + ui::ModalType GetModalType() const override; + bool ShouldShowCloseButton() const override; + bool ShouldShowWindowTitle() const override; + void OnDialogInitialized() override; + + void OnAcceptButtonClicked(); + void OnWindowClosing(); + void CreateChildViews(views::Widget* parent); +}; + +#endif // BRAVE_BROWSER_UI_VIEWS_CRASH_REPORT_PERMISSION_ASK_DIALOG_VIEW_H_ diff --git a/chromium_src/chrome/browser/ui/session_crashed_bubble.h b/chromium_src/chrome/browser/ui/session_crashed_bubble.h new file mode 100644 index 000000000000..5e71ab9d5ebe --- /dev/null +++ b/chromium_src/chrome/browser/ui/session_crashed_bubble.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2021 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_CHROMIUM_SRC_CHROME_BROWSER_UI_SESSION_CRASHED_BUBBLE_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_SESSION_CRASHED_BUBBLE_H_ + +#define ShowIfNotOffTheRecordProfile \ + ShowIfNotOffTheRecordProfileBrave(Browser* browser); \ + static void ShowIfNotOffTheRecordProfile + +#include "../../../../../chrome/browser/ui/session_crashed_bubble.h" + +#undef ShowIfNotOffTheRecordProfile + +#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_SESSION_CRASHED_BUBBLE_H_ diff --git a/chromium_src/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chromium_src/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 992520fdf958..d25839d3aa34 100644 --- a/chromium_src/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chromium_src/chrome/browser/ui/startup/startup_browser_creator_impl.cc @@ -4,10 +4,12 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "brave/browser/ui/startup/default_brave_browser_prompt.h" +#include "chrome/browser/ui/session_crashed_bubble.h" #include "chrome/browser/ui/startup/google_api_keys_infobar_delegate.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/confirm_infobar_delegate.h" +#define ShowIfNotOffTheRecordProfile ShowIfNotOffTheRecordProfileBrave #define GoogleApiKeysInfoBarDelegate BraveGoogleKeysInfoBarDelegate class BraveGoogleKeysInfoBarDelegate { @@ -27,3 +29,4 @@ class BraveGoogleKeysInfoBarDelegate { #undef BRAVE_STARTUPBROWSERCREATORIMPL_DETERMINEURLSANDLAUNCH #undef GoogleApiKeysInfoBarDelegate #undef ShowDefaultBrowserPrompt +#undef ShowIfNotOffTheRecordProfile diff --git a/test/BUILD.gn b/test/BUILD.gn index dc84b9ad319c..abd0bb7ee86d 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -151,7 +151,7 @@ test("brave_unit_tests") { "//brave/browser/content_settings:unit_tests", "//brave/browser/ethereum_remote_client/buildflags", "//brave/browser/first_run:unit_tests", - "//brave/browser/metrics/test:brave_metrics_unit_tests", + "//brave/browser/metrics:brave_metrics_unit_tests", "//brave/browser/net", "//brave/browser/new_tab:unittest", "//brave/browser/permissions:unit_tests", @@ -622,6 +622,7 @@ if (!is_android) { "//brave/browser/ui/toolbar/brave_app_menu_model_browsertest.cc", "//brave/browser/ui/views/bookmarks/bookmark_bar_browsertest.cc", "//brave/browser/ui/views/brave_actions/brave_actions_container_browsertest.cc", + "//brave/browser/ui/views/crash_report_permission_ask_dialog_browsertest.cc", "//brave/browser/ui/views/omnibox/brave_omnibox_view_views_browsertest.cc", "//brave/browser/ui/views/omnibox/omnibox_autocomplete_browsertest.cc", "//brave/browser/ui/views/profiles/brave_profile_menu_view_browsertest.cc",