Create toast specification

Implements the toast specification class so that users can specify how
what should be shown on the toast. Users must go through the
ToastSpecification::Builder() to construct the specification since the
builder enforces design invariants about the toast.

Fixed: 358606511
Change-Id: I253d3b86b3c7361a968ec417efee8aeb36cab0f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5788918
Code-Coverage: [email protected] <[email protected]>
Commit-Queue: Steven Luong <[email protected]>
Reviewed-by: David Pennington <[email protected]>
Reviewed-by: Eshwar Stalin <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1343004}
diff --git a/chrome/browser/ui/toasts/toast_specification.cc b/chrome/browser/ui/toasts/toast_specification.cc
new file mode 100644
index 0000000..efc6d31
--- /dev/null
+++ b/chrome/browser/ui/toasts/toast_specification.cc
@@ -0,0 +1,91 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/toasts/toast_specification.h"
+
+#include <memory>
+
+#include "base/check.h"
+#include "base/functional/callback.h"
+#include "base/functional/callback_forward.h"
+#include "base/types/pass_key.h"
+#include "ui/base/models/simple_menu_model.h"
+
+ToastSpecification::Builder::Builder(const gfx::VectorIcon& icon,
+                                     int body_string_id)
+    : toast_specification_(
+          std::make_unique<ToastSpecification>(base::PassKey<Builder>(),
+                                               icon,
+                                               body_string_id)) {}
+
+ToastSpecification::Builder::~Builder() {
+  // Verify that ToastSpecification::Builder::Build() has been called
+  // so the toast specification is completely built.
+  CHECK(!toast_specification_);
+}
+
+ToastSpecification::Builder& ToastSpecification::Builder::AddCloseButton() {
+  toast_specification_->AddCloseButton();
+  return *this;
+}
+
+ToastSpecification::Builder& ToastSpecification::Builder::AddActionButton(
+    int action_button_string_id,
+    base::RepeatingClosure closure) {
+  toast_specification_->AddActionButton(action_button_string_id,
+                                        std::move(closure));
+  return *this;
+}
+
+ToastSpecification::Builder& ToastSpecification::Builder::AddMenu(
+    std::unique_ptr<ui::SimpleMenuModel> menu_model) {
+  toast_specification_->AddMenu(std::move(menu_model));
+  return *this;
+}
+
+ToastSpecification::Builder& ToastSpecification::Builder::AddPersistance() {
+  toast_specification_->AddPersistance();
+  return *this;
+}
+
+std::unique_ptr<ToastSpecification> ToastSpecification::Builder::Build() {
+  ValidateSpecification();
+  return std::move(toast_specification_);
+}
+
+void ToastSpecification::Builder::ValidateSpecification() {
+  // Toasts with an action button must have a close button and not a menu.
+  if (toast_specification_->action_button_string_id().has_value()) {
+    CHECK(toast_specification_->has_close_button());
+    CHECK(!toast_specification_->menu_model());
+  }
+}
+
+ToastSpecification::ToastSpecification(
+    base::PassKey<ToastSpecification::Builder>,
+    const gfx::VectorIcon& icon,
+    int string_id)
+    : icon_(icon), body_string_id_(string_id) {}
+
+ToastSpecification::~ToastSpecification() = default;
+
+void ToastSpecification::AddCloseButton() {
+  has_close_button_ = true;
+}
+
+void ToastSpecification::AddActionButton(int string_id,
+                                         base::RepeatingClosure closure) {
+  CHECK(!closure.is_null());
+  action_button_string_id_ = string_id;
+  action_button_closure_ = std::move(closure);
+}
+
+void ToastSpecification::AddMenu(
+    std::unique_ptr<ui::SimpleMenuModel> menu_model) {
+  menu_model_ = std::move(menu_model);
+}
+
+void ToastSpecification::AddPersistance() {
+  is_persistent_toast_ = true;
+}