ChromeLabs: Adding lab descriptions and flexlayout formatting

Bug: 1145666
Change-Id: I452ba10bb5fab5cada0aa072d9c33f0ae79bab37
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2567985
Commit-Queue: Elaine Chien <[email protected]>
Reviewed-by: Scott Violet <[email protected]>
Reviewed-by: Thomas Lukaszewicz <[email protected]>
Cr-Commit-Position: refs/heads/master@{#833810}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ded9b6e..4741b92 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4370,7 +4370,7 @@
      FEATURE_VALUE_TYPE(features::kDoubleTapToZoomInTabletMode)},
 #endif  // defined(OS_CHROMEOS)
 
-    {"read-later", flag_descriptions::kReadLaterName,
+    {flag_descriptions::kReadLaterFlagId, flag_descriptions::kReadLaterName,
      flag_descriptions::kReadLaterDescription, kOsDesktop | kOsAndroid,
      FEATURE_VALUE_TYPE(reading_list::switches::kReadLater)},
 
@@ -6568,7 +6568,8 @@
      flag_descriptions::kContentSettingsRedesignDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kContentSettingsRedesign)},
 
-    {"enable-tab-search", flag_descriptions::kEnableTabSearchName,
+    {flag_descriptions::kEnableTabSearchFlagId,
+     flag_descriptions::kEnableTabSearchName,
      flag_descriptions::kEnableTabSearchDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kTabSearch)},
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 016f1fa..ce79fd4 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -977,6 +977,7 @@
     "Enable using server-provided resource loading hints to provide a preview "
     "over slow network connections.";
 
+const char kEnableTabSearchFlagId[] = "enable-tab-search";
 const char kEnableTabSearchName[] = "Enable Tab Search";
 const char kEnableTabSearchDescription[] =
     "Enable the Tab Search feature in Top Chrome UI, which will show a popup "
@@ -1943,6 +1944,7 @@
     "Allows raw / unsanitized clipboard content to be read and written. "
     "See https://github.com/WICG/raw-clipboard-access.";
 
+const char kReadLaterFlagId[] = "read-later";
 const char kReadLaterName[] = "Read Later";
 const char kReadLaterDescription[] =
     "Allow users to save tabs for later. Enables a new button and menu for "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 0d653a2..daa901b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -573,6 +573,7 @@
 extern const char kEnableSubresourceRedirectName[];
 extern const char kEnableSubresourceRedirectDescription[];
 
+extern const char kEnableTabSearchFlagId[];
 extern const char kEnableTabSearchName[];
 extern const char kEnableTabSearchDescription[];
 
@@ -1133,6 +1134,7 @@
 extern const char kRawClipboardName[];
 extern const char kRawClipboardDescription[];
 
+extern const char kReadLaterFlagId[];
 extern const char kReadLaterName[];
 extern const char kReadLaterDescription[];
 
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc
index c3249a4..44f3121 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc
@@ -10,50 +10,55 @@
 #include "chrome/browser/ui/webui/flags_ui.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/flags_ui/pref_service_flags_storage.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/views/background.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/layout_provider.h"
 
 namespace {
 
 ChromeLabsBubbleView* g_chrome_labs_bubble = nullptr;
 
-}  // namespace
-
-// TODO(elainechien): Add screenshots and strings for translation when UI is
-// finished.
 class ChromeLabsFooter : public views::View {
  public:
   ChromeLabsFooter() {
     SetLayoutManager(std::make_unique<views::FlexLayout>())
         ->SetOrientation(views::LayoutOrientation::kVertical);
-    AddChildView(views::Builder<views::Label>()
-                     .CopyAddressTo(&restart_label_)
-                     .SetText(base::ASCIIToUTF16(
-                         "Your changes will take effect the next time you "
-                         "relaunch Google Chrome."))
-                     .SetMultiLine(true)
-                     .Build());
+    AddChildView(
+        views::Builder<views::Label>()
+            .CopyAddressTo(&restart_label_)
+            .SetText(base::ASCIIToUTF16(
+                "Your changes will take effect the next time you "
+                "relaunch Google Chrome."))
+            .SetMultiLine(true)
+            .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+            .SetProperty(views::kFlexBehaviorKey,
+                         views::FlexSpecification(
+                             views::MinimumFlexSizeRule::kPreferred,
+                             views::MaximumFlexSizeRule::kPreferred, true))
+            .Build());
     AddChildView(views::Builder<views::MdTextButton>()
                      .CopyAddressTo(&restart_button_)
                      .SetCallback(base::BindRepeating(&chrome::AttemptRestart))
                      .SetText(base::ASCIIToUTF16("Relaunch"))
                      .Build());
-    restart_label_->SizeToFit(
-        restart_button_->CalculatePreferredSize().width());
+    SetBackground(views::CreateSolidBackground(gfx::kGoogleGrey200));
+    SetBorder(views::CreateEmptyBorder(
+        views::LayoutProvider::Get()->GetInsetsMetric(views::INSETS_DIALOG)));
+    SetProperty(
+        views::kFlexBehaviorKey,
+        views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                                 views::MaximumFlexSizeRule::kPreferred, true));
   }
-  // views::View
-  gfx::Size CalculatePreferredSize() const override {
-    int width = restart_button_->CalculatePreferredSize().width();
-    int height = GetHeightForWidth(width);
-    return gfx::Size(width, height);
-  }
-
  private:
   views::MdTextButton* restart_button_;
   views::Label* restart_label_;
 };
 
+}  // namespace
+
 // static
 void ChromeLabsBubbleView::Show(views::View* anchor_view) {
   g_chrome_labs_bubble = new ChromeLabsBubbleView(
@@ -73,28 +78,36 @@
   SetShowCloseButton(true);
   SetTitle(base::ASCIIToUTF16("Chrome Labs"));
   SetLayoutManager(std::make_unique<views::FlexLayout>())
-      ->SetOrientation(views::LayoutOrientation::kVertical)
-      .SetDefault(views::kMarginsKey, gfx::Insets(5));
+      ->SetOrientation(views::LayoutOrientation::kVertical);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
+  set_margins(gfx::Insets(0));
 
   // TODO(elainechien): ChromeOS specific logic for creating FlagsStorage
   flags_storage_ = std::make_unique<flags_ui::PrefServiceFlagsStorage>(
       g_browser_process->local_state());
   flags_state_ = about_flags::GetCurrentFlagsState();
 
-  menu_item_container_ = AddChildView(std::make_unique<views::View>());
+  menu_item_container_ = AddChildView(
+      views::Builder<views::View>()
+          .SetProperty(views::kFlexBehaviorKey,
+                       views::FlexSpecification(
+                           views::MinimumFlexSizeRule::kScaleToZero,
+                           views::MaximumFlexSizeRule::kPreferred, true))
+          .Build());
   menu_item_container_->SetLayoutManager(std::make_unique<views::FlexLayout>())
-      ->SetOrientation(views::LayoutOrientation::kHorizontal)
+      ->SetOrientation(views::LayoutOrientation::kVertical)
       .SetDefault(views::kMarginsKey, gfx::Insets(10));
 
   // Create each lab item.
-  std::vector<std::string> lab_internal_names = model_->GetLabInfo();
-  for (const auto& internal_name : lab_internal_names) {
+  const std::vector<LabInfo>& all_labs = model_->GetLabInfo();
+  for (const auto& lab : all_labs) {
     const flags_ui::FeatureEntry* entry =
-        flags_state_->FindFeatureEntryByName(internal_name);
+        flags_state_->FindFeatureEntryByName(lab.internal_name);
     DCHECK_EQ(entry->type, flags_ui::FeatureEntry::FEATURE_VALUE);
     int default_index = GetIndexOfEnabledLabState(entry);
     menu_item_container_->AddChildView(
-        CreateLabItem(internal_name, default_index, entry));
+        CreateLabItem(lab, default_index, entry));
   }
   // TODO(elainechien): Build UI for 0 experiments case.
   DCHECK(menu_item_container_->children().size() >= 1);
@@ -104,7 +117,7 @@
 }
 
 std::unique_ptr<ChromeLabsItemView> ChromeLabsBubbleView::CreateLabItem(
-    std::string internal_name,
+    const LabInfo& lab,
     int default_index,
     const flags_ui::FeatureEntry* entry) {
   auto combobox_callback = [](ChromeLabsBubbleView* bubble_view,
@@ -117,9 +130,16 @@
     bubble_view->ShowRelaunchPrompt();
   };
 
-  return std::make_unique<ChromeLabsItemView>(
-      internal_name, default_index, entry,
-      base::BindRepeating(combobox_callback, this, internal_name));
+  std::unique_ptr<ChromeLabsItemView> item_view =
+      std::make_unique<ChromeLabsItemView>(
+          lab, default_index, entry,
+          base::BindRepeating(combobox_callback, this, lab.internal_name));
+
+  item_view->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                               views::MaximumFlexSizeRule::kPreferred, true));
+  return item_view;
 }
 
 int ChromeLabsBubbleView::GetIndexOfEnabledLabState(
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h
index ec6464f5a..a2e1405f 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h
@@ -13,6 +13,9 @@
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 // TODO(elainechien): Use composition instead of inheritance.
+// TODO(elainechien): Add screenshots and strings for translation when UI is
+// finished.
+// TODO(elainechien): Formatting for items in child views.
 class ChromeLabsBubbleView : public views::BubbleDialogDelegateView {
  public:
   static void Show(views::View* anchor_view);
@@ -35,7 +38,7 @@
                        std::unique_ptr<ChromeLabsBubbleViewModel> model);
 
   std::unique_ptr<ChromeLabsItemView> CreateLabItem(
-      std::string internal_name,
+      const LabInfo& lab,
       int default_index,
       const flags_ui::FeatureEntry* entry);
 
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc
index 2e70fd23..f5d163e 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc
@@ -4,13 +4,14 @@
 
 #include "chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/flag_descriptions.h"
 
 ChromeLabsBubbleViewModel::ChromeLabsBubbleViewModel() {
   SetUpLabs();
 }
 
-std::vector<std::string> ChromeLabsBubbleViewModel::GetLabInfo() const {
-  return lab_internal_names_;
+const std::vector<LabInfo>& ChromeLabsBubbleViewModel::GetLabInfo() const {
+  return lab_info_;
 }
 
 // TODO(elainechien): Explore better ways to allow developers to add their
@@ -19,7 +20,19 @@
 // (Default, Enabled, Disabled states). Experiments with multiple parameters may
 // be considered in the future.
 void ChromeLabsBubbleViewModel::SetUpLabs() {
-  lab_internal_names_.push_back("read-later");
+  // Read Later.
+  lab_info_.emplace_back(LabInfo(
+      flag_descriptions::kReadLaterFlagId, base::ASCIIToUTF16("Reading List"),
+      base::ASCIIToUTF16(
+          "Right click on a tab or click the star to add tabs to a reading "
+          "list. Access from the Bookmarks bar.")));
+
+  // Tab Search.
+  lab_info_.emplace_back(
+      LabInfo(flag_descriptions::kEnableTabSearchFlagId,
+              base::ASCIIToUTF16("Tab Search"),
+              base::ASCIIToUTF16("Enable a popup bubble in Top Chrome UI to "
+                                 "search over currently open tabs.")));
 }
 
 ChromeLabsBubbleViewModel::~ChromeLabsBubbleViewModel() = default;
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h
index a299f52..6202b3f 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h
@@ -8,17 +8,33 @@
 #include <vector>
 #include "base/strings/string16.h"
 
+// Currently there are differences in both visible name and visible description
+// between about_flags and what we want for Chrome Labs. We are coordinating to
+// match these. LabInfo struct can be removed after that.
+struct LabInfo {
+  LabInfo(const std::string& internal_name,
+          const base::string16& visible_name,
+          const base::string16& visible_description)
+      : internal_name(internal_name),
+        visible_name(visible_name),
+        visible_description(visible_description) {}
+
+  std::string internal_name;
+  base::string16 visible_name;
+  base::string16 visible_description;
+};
+
 class ChromeLabsBubbleViewModel {
  public:
   ChromeLabsBubbleViewModel();
   ~ChromeLabsBubbleViewModel();
 
-  std::vector<std::string> GetLabInfo() const;
+  const std::vector<LabInfo>& GetLabInfo() const;
 
  private:
   void SetUpLabs();
 
-  std::vector<std::string> lab_internal_names_;
+  std::vector<LabInfo> lab_info_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_MODEL_H_
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc
index 6a7c0e9..0e35b72 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc
@@ -3,9 +3,11 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/toolbar/chrome_labs_item_view.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
 
 class LabsComboboxModel : public ui::ComboboxModel {
  public:
@@ -29,18 +31,29 @@
 };
 
 ChromeLabsItemView::ChromeLabsItemView(
-    std::string internal_name,
+    const LabInfo& lab,
     int default_index,
     const flags_ui::FeatureEntry* feature_entry,
     base::RepeatingCallback<void(ChromeLabsItemView* item_view)>
         combobox_callback)
-    : internal_name_(internal_name), feature_entry_(feature_entry) {
+    : feature_entry_(feature_entry) {
   SetLayoutManager(std::make_unique<views::FlexLayout>())
-      ->SetOrientation(views::LayoutOrientation::kHorizontal)
+      ->SetOrientation(views::LayoutOrientation::kVertical)
       .SetDefault(views::kMarginsKey, gfx::Insets(10));
   AddChildView(views::Builder<views::Label>()
-                   .SetText(base::ASCIIToUTF16(feature_entry->visible_name))
+                   .SetText(lab.visible_name)
+                   .SetHorizontalAlignment(gfx::ALIGN_LEFT)
                    .Build());
+  AddChildView(
+      views::Builder<views::Label>()
+          .SetText(lab.visible_description)
+          .SetMultiLine(true)
+          .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+          .SetProperty(views::kFlexBehaviorKey,
+                       views::FlexSpecification(
+                           views::MinimumFlexSizeRule::kPreferred,
+                           views::MaximumFlexSizeRule::kPreferred, true))
+          .Build());
   AddChildView(views::Builder<views::Combobox>()
                    .CopyAddressTo(&lab_state_combobox_)
                    .SetOwnedModel(std::make_unique<LabsComboboxModel>(
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h
index 2de6eed8..e11e5bb 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h
@@ -10,10 +10,12 @@
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/view.h"
 
+struct LabInfo;
+
 class ChromeLabsItemView : public views::View {
  public:
   ChromeLabsItemView(
-      std::string internal_name,
+      const LabInfo& lab,
       int default_index,
       const flags_ui::FeatureEntry* feature_entry,
       base::RepeatingCallback<void(ChromeLabsItemView* item_view)>
@@ -31,8 +33,6 @@
   // Combobox with selected state of the lab.
   views::Combobox* lab_state_combobox_;
 
-  std::string internal_name_;
-
   const flags_ui::FeatureEntry* feature_entry_;
 };