diff --git a/browser/BUILD.gn b/browser/BUILD.gn index edc79926ebe..ec090495a8c 100644 --- a/browser/BUILD.gn +++ b/browser/BUILD.gn @@ -151,6 +151,7 @@ source_set("browser_process") { "//brave/components/ntp_background_images/browser", "//brave/components/ntp_tiles", "//brave/components/p3a", + "//brave/components/permissions", "//brave/components/resources", "//brave/components/sidebar/buildflags", "//brave/components/speedreader:buildflags", diff --git a/chromium_src/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc b/chromium_src/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc index 33f19cac613..c7dfa153d2e 100644 --- a/chromium_src/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc +++ b/chromium_src/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc @@ -5,9 +5,17 @@ #include +#include "base/feature_list.h" +#include "brave/components/permissions/permission_lifetime_utils.h" +#include "components/grit/brave_components_strings.h" +#include "components/permissions/features.h" +#include "components/permissions/permission_prompt.h" #include "components/permissions/permission_request.h" #include "third_party/widevine/cdm/buildflags.h" +#include "ui/base/models/combobox_model.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" +#include "ui/views/controls/combobox/combobox.h" +#include "ui/views/layout/box_layout.h" #include "ui/views/window/dialog_delegate.h" #if BUILDFLAG(ENABLE_WIDEVINE) @@ -28,13 +36,13 @@ namespace { class DontAskAgainCheckbox : public views::Checkbox { public: explicit DontAskAgainCheckbox(WidevinePermissionRequest* request); + DontAskAgainCheckbox(const DontAskAgainCheckbox&) = delete; + DontAskAgainCheckbox& operator=(const DontAskAgainCheckbox&) = delete; private: void ButtonPressed(); WidevinePermissionRequest* request_; - - DISALLOW_COPY_AND_ASSIGN(DontAskAgainCheckbox); }; DontAskAgainCheckbox::DontAskAgainCheckbox(WidevinePermissionRequest* request) @@ -87,10 +95,88 @@ void AddAdditionalWidevineViewControlsIfNeeded( views::BubbleDialogDelegateView* dialog_delegate_view, const std::vector& requests) {} #endif + +// Custom combobox, shows permission lifetime options and applies selected value +// to all permissions currently visible in the bubble. +class PermissionLifetimeCombobox : public views::Combobox, + public ui::ComboboxModel { + public: + explicit PermissionLifetimeCombobox( + permissions::PermissionPrompt::Delegate* delegate) + : delegate_(delegate), + lifetime_options_(permissions::CreatePermissionLifetimeOptions()) { + DCHECK(delegate_); + SetCallback(base::BindRepeating(&PermissionLifetimeCombobox::OnItemSelected, + base::Unretained(this))); + SetModel(this); + OnItemSelected(); + } + + PermissionLifetimeCombobox(const PermissionLifetimeCombobox&) = delete; + PermissionLifetimeCombobox& operator=(const PermissionLifetimeCombobox&) = + delete; + + // ui::ComboboxModel: + int GetItemCount() const override { return lifetime_options_.size(); } + + base::string16 GetItemAt(int index) const override { + return lifetime_options_[index].label; + } + + private: + void OnItemSelected() { + const auto& lifetime = lifetime_options_[GetSelectedIndex()].lifetime; + DLOG(INFO) << "Set permission lifetime " + << (lifetime ? lifetime->InSeconds() : -1); + // TODO(https://github.com/brave/brave-browser/issues/14126): Set the + // lifetime for all current requests. + // for (auto* request : delegate_->Requests()) { + // request->SetLifetime(lifetime); + // } + } + + permissions::PermissionPrompt::Delegate* const delegate_; + std::vector lifetime_options_; +}; + +void AddPermissionLifetimeComboboxIfNeeded( + views::BubbleDialogDelegateView* dialog_delegate_view, + permissions::PermissionPrompt::Delegate* delegate) { + if (!base::FeatureList::IsEnabled( + permissions::features::kPermissionLifetime)) { + return; + } + + // Create a single line container for a label and a combobox. + auto container = std::make_unique(); + container->SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), + views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_RELATED_BUTTON_HORIZONTAL))); + + // Add the label. + auto* label = new views::Label( + l10n_util::GetStringUTF16(IDS_PERMISSIONS_BUBBLE_LIFETIME_COMBOBOX_LABEL), + views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY); + label->SetMultiLine(true); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + container->AddChildView(label); + + // Add the combobox. + auto* combobox = new PermissionLifetimeCombobox(delegate); + container->AddChildView(combobox); + static_cast(container->GetLayoutManager()) + ->SetFlexForView(combobox, 1); + + // Add the container to the view. + dialog_delegate_view->AddChildView(std::move(container)); +} + } // namespace -#define BRAVE_PERMISSION_PROMPT_BUBBLE_VIEW \ - AddAdditionalWidevineViewControlsIfNeeded(this, delegate_->Requests()); +#define BRAVE_PERMISSION_PROMPT_BUBBLE_VIEW \ + AddAdditionalWidevineViewControlsIfNeeded(this, delegate_->Requests()); \ + AddPermissionLifetimeComboboxIfNeeded(this, delegate_); #include "../../../../../../../chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc" #undef BRAVE_PERMISSION_PROMPT_BUBBLE_VIEW diff --git a/chromium_src/components/permissions/features.cc b/chromium_src/components/permissions/features.cc new file mode 100644 index 00000000000..bb2b3631f84 --- /dev/null +++ b/chromium_src/components/permissions/features.cc @@ -0,0 +1,16 @@ +/* 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 "../../../../components/permissions/features.cc" + +namespace permissions { +namespace features { + +// Enables the option of an automatic permission expiration time. +const base::Feature kPermissionLifetime{"PermissionLifetime", + base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace features +} // namespace permissions diff --git a/chromium_src/components/permissions/features.h b/chromium_src/components/permissions/features.h new file mode 100644 index 00000000000..135c82d3408 --- /dev/null +++ b/chromium_src/components/permissions/features.h @@ -0,0 +1,19 @@ +/* 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_COMPONENTS_PERMISSIONS_FEATURES_H_ +#define BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_FEATURES_H_ + +#include "../../../../components/permissions/features.h" + +namespace permissions { +namespace features { + +extern const base::Feature kPermissionLifetime; + +} // namespace features +} // namespace permissions + +#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_PERMISSIONS_FEATURES_H_ diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn new file mode 100644 index 00000000000..6477732da08 --- /dev/null +++ b/components/permissions/BUILD.gn @@ -0,0 +1,14 @@ +source_set("permissions") { + sources = [ + "permission_lifetime_utils.cc", + "permission_lifetime_utils.h", + ] + + deps = [ + "//base", + "//base:i18n", + "//brave/components/resources:strings_grit", + "//components/permissions", + "//ui/base", + ] +} diff --git a/components/permissions/DEPS b/components/permissions/DEPS new file mode 100644 index 00000000000..e7cf2c6ff61 --- /dev/null +++ b/components/permissions/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ui/base", +] diff --git a/components/permissions/permission_lifetime_utils.cc b/components/permissions/permission_lifetime_utils.cc new file mode 100644 index 00000000000..ce2b335291f --- /dev/null +++ b/components/permissions/permission_lifetime_utils.cc @@ -0,0 +1,60 @@ +/* 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/components/permissions/permission_lifetime_utils.h" + +#include + +#include "base/i18n/time_formatting.h" +#include "base/stl_util.h" +#include "components/grit/brave_components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace permissions { + +PermissionLifetimeOption::PermissionLifetimeOption( + base::string16 label, + base::Optional lifetime) + : label(std::move(label)), lifetime(std::move(lifetime)) {} + +PermissionLifetimeOption::PermissionLifetimeOption( + const PermissionLifetimeOption&) = default; +PermissionLifetimeOption& PermissionLifetimeOption::operator=( + const PermissionLifetimeOption&) = default; +PermissionLifetimeOption::PermissionLifetimeOption( + PermissionLifetimeOption&&) noexcept = default; +PermissionLifetimeOption& PermissionLifetimeOption::operator=( + PermissionLifetimeOption&&) noexcept = default; +PermissionLifetimeOption::~PermissionLifetimeOption() = default; + +std::vector CreatePermissionLifetimeOptions() { + // TODO(https://github.com/brave/brave-browser/issues/14126): Actualize + // values. + constexpr base::TimeDelta kLifetimes[] = { + base::TimeDelta::FromSeconds(60), base::TimeDelta::FromHours(1), + base::TimeDelta::FromHours(3), base::TimeDelta::FromDays(1), + base::TimeDelta::FromDays(30), + }; + + std::vector options; + options.reserve(1 + base::size(kLifetimes)); + options.emplace_back(PermissionLifetimeOption( + l10n_util::GetStringUTF16( + IDS_PERMISSIONS_BUBBLE_PERMANENT_LIFETIME_OPTION), + base::nullopt)); + + for (const auto& lifetime : kLifetimes) { + base::string16 formatted_time; + const bool format_successful = base::TimeDurationFormat( + lifetime, base::DURATION_WIDTH_WIDE, &formatted_time); + DCHECK(format_successful); + options.emplace_back( + PermissionLifetimeOption(std::move(formatted_time), lifetime)); + } + + return options; +} + +} // namespace permissions diff --git a/components/permissions/permission_lifetime_utils.h b/components/permissions/permission_lifetime_utils.h new file mode 100644 index 00000000000..86047fc858d --- /dev/null +++ b/components/permissions/permission_lifetime_utils.h @@ -0,0 +1,38 @@ +/* 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_COMPONENTS_PERMISSIONS_PERMISSION_LIFETIME_UTILS_H_ +#define BRAVE_COMPONENTS_PERMISSIONS_PERMISSION_LIFETIME_UTILS_H_ + +#include + +#include "base/optional.h" +#include "base/strings/string16.h" +#include "base/time/time.h" + +namespace permissions { + +struct PermissionLifetimeOption { + PermissionLifetimeOption(base::string16 label, + base::Optional lifetime); + PermissionLifetimeOption(const PermissionLifetimeOption&); + PermissionLifetimeOption& operator=(const PermissionLifetimeOption&); + PermissionLifetimeOption(PermissionLifetimeOption&&) noexcept; + PermissionLifetimeOption& operator=(PermissionLifetimeOption&&) noexcept; + ~PermissionLifetimeOption(); + + // Text visible to the user. + base::string16 label; + // If not set, lifetime will not be controlled (i.e. permanent). If set to + // base::TimeDelta(), permission should be alive until eTLD+1 is closed. + base::Optional lifetime; +}; + +// Returns pre-configured permission lifetime options. +std::vector CreatePermissionLifetimeOptions(); + +} // namespace permissions + +#endif // BRAVE_COMPONENTS_PERMISSIONS_PERMISSION_LIFETIME_UTILS_H_ diff --git a/components/resources/brave_components_strings.grd b/components/resources/brave_components_strings.grd index 4eff300530a..6f79241aaf6 100644 --- a/components/resources/brave_components_strings.grd +++ b/components/resources/brave_components_strings.grd @@ -1088,12 +1088,14 @@ Brave Rewards Downloading Component... I understand - - - - + + + + + + diff --git a/components/resources/permissions_strings.grdp b/components/resources/permissions_strings.grdp new file mode 100644 index 00000000000..e8dd65606b2 --- /dev/null +++ b/components/resources/permissions_strings.grdp @@ -0,0 +1,9 @@ + + + + Permission lifetime + + + Permanent + +