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",