CSC status indicator UI element in TabSharingInfoBar

Added a the UI element for a status indicator for Captured Surface
Control (CSC) in TabSharingInfoBar behind the CscStickyPermissions
feature flag.

The logic for when the indicator is visible and the code to open the
permissions dialog when it is clicked will be added in follow-up CLs.

Bug: TBD
Change-Id: Iccb49f0b8b6c0f7e48253b2bf9edfc631da0e982
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5366940
Commit-Queue: Tove Petersson <tovep@chromium.org>
Reviewed-by: Elad Alon <eladalon@chromium.org>
Commit-Queue: Elad Alon <eladalon@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1279592}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3d4c7e23..3551237 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4714,6 +4714,9 @@
       <message name="IDS_TAB_SHARING_INFOBAR_SWITCH_TO_CAPTURED_BUTTON" desc="Text displayed on an infobar button offering to change focus to the capturer if its hostname cannot be determined. (Otherwise, IDS_TAB_SHARING_INFOBAR_SWITCH_TO_BUTTON will be used.)">
        Switch to captured tab
       </message>
+      <message name="IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON" desc="Text informing users that shared tabs can be scrolled and zoomed.">
+        Shared tabs can be scrolled and zoomed
+      </message>
 
       <!-- Tab casting infobar -->
       <message name="IDS_TAB_CASTING_INFOBAR_CASTING_CURRENT_TAB_LABEL" desc="Text displayed on an infobar when current tab is being cast. The placeholder text (DEVICE_NAME) represents the name of the cast receiver.">
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON.png.sha1
new file mode 100644
index 0000000..8e32bc75
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON.png.sha1
@@ -0,0 +1 @@
+b2e4797bfdc58a4ec2d0207ca18d7d6a5c562b4a
\ No newline at end of file
diff --git a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc
index f10bbd22..d3f93446 100644
--- a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc
+++ b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc
@@ -24,11 +24,16 @@
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_features.h"
 #include "net/base/url_util.h"
 #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/strings/grit/ui_strings.h"
 
+namespace {
+constexpr int kCscPermissionButtonIconHeight = 16;
+}  // namespace
+
 class TabSharingInfoBarDelegate::TabSharingInfoBarDelegateButton {
  public:
   TabSharingInfoBarDelegateButton() = default;
@@ -155,6 +160,30 @@
   const bool focus_target_is_capturer_;
 };
 
+class TabSharingInfoBarDelegate::CscPermissionButton
+    : public TabSharingInfoBarDelegate::TabSharingInfoBarDelegateButton {
+ public:
+  CscPermissionButton() = default;
+  ~CscPermissionButton() override = default;
+
+  void Click(infobars::InfoBar* infobar) override {
+    // TODO(crbug.com/324468211): Implement
+  }
+
+  std::u16string GetLabel() const override {
+    return l10n_util::GetStringUTF16(
+        IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON);
+  }
+
+  bool IsEnabled() const override { return true; }
+
+  ui::ImageModel GetImage() const override {
+    return ui::ImageModel::FromVectorIcon(vector_icons::kTouchpadMouseIcon,
+                                          ui::kColorSysPrimary,
+                                          kCscPermissionButtonIconHeight);
+  }
+};
+
 namespace {
 
 std::u16string GetMessageTextCastingNoSinkName(
@@ -254,6 +283,13 @@
     quick_nav_button_ =
         std::make_unique<SwitchToTabButton>(*focus_target, shared_tab);
   }
+
+  // TODO(crbug.com/324468211): Initialize csc_permission_button_ only when it
+  // should be shown
+  if (base::FeatureList::IsEnabled(
+          features::kCapturedSurfaceControlStickyPermissions)) {
+    csc_permission_button_ = std::make_unique<CscPermissionButton>();
+  }
 }
 
 TabSharingInfoBarDelegate::~TabSharingInfoBarDelegate() = default;
@@ -307,16 +343,16 @@
     case kQuickNav:
       DCHECK(quick_nav_button_);
       return quick_nav_button_->GetLabel();
+
+    case kCscPermission:
+      DCHECK(csc_permission_button_);
+      return csc_permission_button_->GetLabel();
   }
   NOTREACHED_NORETURN();
 }
 
 ui::ImageModel TabSharingInfoBarDelegate::GetButtonImage(
     InfoBarButton button) const {
-  if (!favicons_used_for_switch_to_tab_button_) {
-    return ui::ImageModel();
-  }
-
   switch (button) {
     case kNone:
       break;
@@ -326,11 +362,17 @@
 
     case kShareThisTabInstead:
       DCHECK(share_this_tab_instead_button_);
-      return share_this_tab_instead_button_->GetImage();
+      return favicons_used_for_switch_to_tab_button_
+                 ? share_this_tab_instead_button_->GetImage()
+                 : ui::ImageModel();
 
     case kQuickNav:
       DCHECK(quick_nav_button_);
       return quick_nav_button_->GetImage();
+
+    case kCscPermission:
+      DCHECK(csc_permission_button_);
+      return csc_permission_button_->GetImage();
   }
   NOTREACHED_NORETURN();
 }
@@ -350,6 +392,10 @@
     case kQuickNav:
       DCHECK(quick_nav_button_);
       return quick_nav_button_->IsEnabled();
+
+    case kCscPermission:
+      DCHECK(csc_permission_button_);
+      return csc_permission_button_->IsEnabled();
   }
   NOTREACHED_NORETURN();
 }
@@ -370,13 +416,18 @@
     case kQuickNav:
       DCHECK(quick_nav_button_);
       return quick_nav_button_->GetTooltip();
+
+    case kCscPermission:
+      DCHECK(csc_permission_button_);
+      return csc_permission_button_->GetTooltip();
   }
   NOTREACHED_NORETURN();
 }
 
 int TabSharingInfoBarDelegate::GetButtons() const {
   return kStop | (share_this_tab_instead_button_ ? kShareThisTabInstead : 0) |
-         (quick_nav_button_ ? kQuickNav : 0);
+         (quick_nav_button_ ? kQuickNav : 0) |
+         (csc_permission_button_ ? kCscPermission : 0);
 }
 
 bool TabSharingInfoBarDelegate::Stop() {
@@ -396,6 +447,12 @@
   return false;
 }
 
+bool TabSharingInfoBarDelegate::OpenCscPermissions() {
+  DCHECK(csc_permission_button_);
+  csc_permission_button_->Click(infobar());
+  return false;
+}
+
 bool TabSharingInfoBarDelegate::IsCloseable() const {
   return false;
 }
diff --git a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h
index dc8e92e..bae2ca8 100644
--- a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h
+++ b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h
@@ -49,6 +49,7 @@
     kStop = 1 << 0,
     kShareThisTabInstead = 1 << 1,
     kQuickNav = 1 << 2,
+    kCscPermission = 1 << 3,
   };
 
   enum class ButtonState {
@@ -69,6 +70,7 @@
   class TabSharingInfoBarDelegateButton;
   class ShareTabInsteadButton;
   class SwitchToTabButton;
+  class CscPermissionButton;
 
   // Creates a tab sharing infobar, which has 1-2 buttons.
   //
@@ -103,6 +105,7 @@
   bool Stop();
   bool ShareThisTabInstead();
   bool QuickNav();
+  bool OpenCscPermissions();
 
   // InfoBarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
@@ -140,6 +143,7 @@
 
   std::unique_ptr<ShareTabInsteadButton> share_this_tab_instead_button_;
   std::unique_ptr<SwitchToTabButton> quick_nav_button_;
+  std::unique_ptr<CscPermissionButton> csc_permission_button_;
 };
 
 std::unique_ptr<infobars::InfoBar> CreateTabSharingInfoBar(
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc
index 83e34d85..93768871 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc
+++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc
@@ -9,18 +9,25 @@
 
 #include "base/functional/bind.h"
 #include "build/build_config.h"
+#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "components/infobars/content/content_infobar_manager.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
+#include "ui/views/layout/layout_provider.h"
 #include "ui/views/style/platform_style.h"
 #include "ui/views/view_class_properties.h"
 
+namespace {
+constexpr auto kCscPermissionButtonInsets = gfx::Insets::VH(4, 8);
+}
+
 TabSharingInfoBar::TabSharingInfoBar(
     std::unique_ptr<TabSharingInfoBarDelegate> delegate)
     : InfoBarView(std::move(delegate)) {
@@ -31,9 +38,12 @@
   const auto buttons = delegate_ptr->GetButtons();
   const auto create_button = [&](TabSharingInfoBarDelegate::InfoBarButton type,
                                  void (TabSharingInfoBar::*click_function)()) {
+    const bool use_text_color_for_icon =
+        type != TabSharingInfoBarDelegate::kCscPermission;
     auto* button = AddChildView(std::make_unique<views::MdTextButton>(
         base::BindRepeating(click_function, base::Unretained(this)),
-        delegate_ptr->GetButtonLabel(type)));
+        delegate_ptr->GetButtonLabel(type), views::style::CONTEXT_BUTTON_MD,
+        use_text_color_for_icon));
     button->SetProperty(
         views::kMarginsKey,
         gfx::Insets::VH(ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -68,6 +78,18 @@
                       &TabSharingInfoBar::QuickNavButtonPressed);
   }
 
+  if (buttons & TabSharingInfoBarDelegate::kCscPermission) {
+    csc_permission_button_ =
+        create_button(TabSharingInfoBarDelegate::kCscPermission,
+                      &TabSharingInfoBar::CscPermissionButtonPressed);
+    csc_permission_button_->SetStyle(ui::ButtonStyle::kDefault);
+    csc_permission_button_->SetCornerRadius(
+        GetLayoutConstant(TOOLBAR_CORNER_RADIUS));
+    csc_permission_button_->SetCustomPadding(kCscPermissionButtonInsets);
+    csc_permission_button_->SetTextColorId(
+        views::Button::ButtonState::STATE_NORMAL, ui::kColorSysOnSurface);
+  }
+
   // TODO(josephjoopark): It seems like link_ isn't always needed, but it's
   // added regardless. See about only adding when necessary.
   link_ = AddChildView(CreateLink(delegate_ptr->GetLinkText()));
@@ -90,6 +112,10 @@
     quick_nav_button_->SizeToPreferredSize();
   }
 
+  if (csc_permission_button_) {
+    csc_permission_button_->SizeToPreferredSize();
+  }
+
   int x = GetStartX();
   Views views;
   views.push_back(label_.get());
@@ -118,6 +144,9 @@
   if (quick_nav_button_) {
     order_of_buttons.push_back(quick_nav_button_);
   }
+  if (csc_permission_button_) {
+    order_of_buttons.push_back(csc_permission_button_);
+  }
 
   if (!views::PlatformStyle::kIsOkButtonLeading) {
     base::ranges::reverse(order_of_buttons);
@@ -160,6 +189,15 @@
   }
 }
 
+void TabSharingInfoBar::CscPermissionButtonPressed() {
+  if (!owner()) {
+    return;  // We're closing; don't call anything, it might access the owner.
+  }
+  if (GetDelegate()->OpenCscPermissions()) {
+    RemoveSelf();
+  }
+}
+
 TabSharingInfoBarDelegate* TabSharingInfoBar::GetDelegate() {
   return static_cast<TabSharingInfoBarDelegate*>(delegate());
 }
@@ -177,9 +215,9 @@
   const int button_spacing = layout_provider->GetDistanceMetric(
       views::DISTANCE_RELATED_BUTTON_HORIZONTAL);
 
-  const int button_count = (stop_button_ ? 1 : 0) +
-                           (share_this_tab_instead_button_ ? 1 : 0) +
-                           (quick_nav_button_ ? 1 : 0);
+  const int button_count =
+      (stop_button_ ? 1 : 0) + (share_this_tab_instead_button_ ? 1 : 0) +
+      (quick_nav_button_ ? 1 : 0) + (csc_permission_button_ ? 1 : 0);
 
   int width =
       (label_->GetText().empty() || button_count == 0) ? 0 : label_spacing;
@@ -191,6 +229,7 @@
                ? share_this_tab_instead_button_->width()
                : 0;
   width += quick_nav_button_ ? quick_nav_button_->width() : 0;
+  width += csc_permission_button_ ? csc_permission_button_->width() : 0;
 
   return width + ((width && !link_->GetText().empty()) ? label_spacing : 0);
 }
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h
index 90f6a9f..5187635a 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h
+++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h
@@ -45,6 +45,7 @@
   void StopButtonPressed();
   void ShareThisTabInsteadButtonPressed();
   void QuickNavButtonPressed();
+  void CscPermissionButtonPressed();
 
   // Returns the width of all content other than the label and link.
   // Layout uses this to determine how much space the label and link can take.
@@ -54,6 +55,7 @@
   raw_ptr<views::MdTextButton> stop_button_ = nullptr;
   raw_ptr<views::MdTextButton> share_this_tab_instead_button_ = nullptr;
   raw_ptr<views::MdTextButton> quick_nav_button_ = nullptr;
+  raw_ptr<views::MdTextButton> csc_permission_button_ = nullptr;
   raw_ptr<views::Link> link_ = nullptr;
 };