Add infrastructure for an internals page for commerce

This patch adds the infra for a basic internals page that currently
just displays the current signed-in user's eligibility for the
shopping list feature. This functions on both content/ based builds
and iOS. The content/ side includes a browser test to ensure the
page actually loads.

Bug: b:274621159
Change-Id: I1ce5ec79b2dbb63981736eea1a28b5b8cf1478b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4389124
Reviewed-by: Colin Blundell <[email protected]>
Commit-Queue: Matthew Jones <[email protected]>
Reviewed-by: Sylvain Defresne <[email protected]>
Reviewed-by: Yue Zhang <[email protected]>
Reviewed-by: Zhiyuan Cai <[email protected]>
Reviewed-by: Dominic Farolino <[email protected]>
Reviewed-by: Dana Fried <[email protected]>
Reviewed-by: John Lee <[email protected]>
Code-Coverage: Findit <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1131205}
diff --git a/components/commerce/ios/browser/BUILD.gn b/components/commerce/ios/browser/BUILD.gn
index 3f3d21c..40c67b7 100644
--- a/components/commerce/ios/browser/BUILD.gn
+++ b/components/commerce/ios/browser/BUILD.gn
@@ -4,6 +4,8 @@
 
 static_library("browser") {
   sources = [
+    "commerce_internals_ui.h",
+    "commerce_internals_ui.mm",
     "commerce_tab_helper.h",
     "commerce_tab_helper.mm",
     "web_state_wrapper.h",
@@ -14,8 +16,12 @@
     "//base",
     "//components/commerce/core:shopping_service",
     "//ios/web",
+    "//ios/web/public",
     "//ios/web/public/js_messaging",
+    "//ios/web/public/webui",
   ]
 
+  public_deps = [ "//components/commerce/core/internals" ]
+
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/components/commerce/ios/browser/commerce_internals_ui.h b/components/commerce/ios/browser/commerce_internals_ui.h
new file mode 100644
index 0000000..af2749b
--- /dev/null
+++ b/components/commerce/ios/browser/commerce_internals_ui.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_COMMERCE_IOS_BROWSER_COMMERCE_INTERNALS_UI_H_
+#define COMPONENTS_COMMERCE_IOS_BROWSER_COMMERCE_INTERNALS_UI_H_
+
+#import "base/functional/callback.h"
+#import "components/commerce/core/internals/commerce_internals_handler.h"
+#import "components/commerce/core/internals/commerce_internals_ui_base.h"
+#import "components/commerce/core/internals/mojom/commerce_internals.mojom.h"
+#import "ios/web/public/webui/web_ui_ios_controller.h"
+
+namespace web {
+class WebUIIOS;
+}  // namespace web
+
+namespace commerce {
+
+class ShoppingService;
+
+// The class supporting init of the iOS version of the internals page.
+class CommerceInternalsUI : public CommerceInternalsUIBase,
+                            public web::WebUIIOSController {
+ public:
+  CommerceInternalsUI(web::WebUIIOS* web_ui,
+                      const std::string& host,
+                      ShoppingService* shopping_service);
+  CommerceInternalsUI(const CommerceInternalsUI&) = delete;
+  CommerceInternalsUI operator&(const CommerceInternalsUI&) = delete;
+  ~CommerceInternalsUI() override;
+};
+
+}  // namespace commerce
+
+#endif  // COMPONENTS_COMMERCE_IOS_BROWSER_COMMERCE_INTERNALS_UI_H_
diff --git a/components/commerce/ios/browser/commerce_internals_ui.mm b/components/commerce/ios/browser/commerce_internals_ui.mm
new file mode 100644
index 0000000..5a6baf0
--- /dev/null
+++ b/components/commerce/ios/browser/commerce_internals_ui.mm
@@ -0,0 +1,52 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "components/commerce/ios/browser/commerce_internals_ui.h"
+
+#import "components/commerce/core/commerce_constants.h"
+#import "components/commerce/core/shopping_service.h"
+#import "components/grit/commerce_internals_resources.h"
+#import "components/grit/commerce_internals_resources_map.h"
+#import "ios/web/public/browser_state.h"
+#import "ios/web/public/web_state.h"
+#import "ios/web/public/webui/web_ui_ios.h"
+#import "ios/web/public/webui/web_ui_ios_data_source.h"
+#import "ui/base/webui/resource_path.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace commerce {
+
+CommerceInternalsUI::CommerceInternalsUI(web::WebUIIOS* web_ui,
+                                         const std::string& host,
+                                         ShoppingService* shopping_service)
+    : CommerceInternalsUIBase(shopping_service),
+      web::WebUIIOSController(web_ui, host) {
+  web::BrowserState* browser_state = web_ui->GetWebState()->GetBrowserState();
+
+  web::WebUIIOSDataSource* source =
+      web::WebUIIOSDataSource::Create(kChromeUICommerceInternalsHost);
+  source->SetDefaultResource(IDR_COMMERCE_INTERNALS_COMMERCE_INTERNALS_HTML);
+  source->UseStringsJs();
+  const base::span<const webui::ResourcePath> resources = base::make_span(
+      kCommerceInternalsResources, kCommerceInternalsResourcesSize);
+
+  for (const auto& resource : resources) {
+    source->AddResourcePath(resource.path, resource.id);
+  }
+
+  web::WebUIIOSDataSource::Add(browser_state, source);
+  web_ui->GetWebState()->GetInterfaceBinderForMainFrame()->AddInterface(
+      base::BindRepeating(&CommerceInternalsUI::BindInterface,
+                          base::Unretained(this)));
+}
+
+CommerceInternalsUI::~CommerceInternalsUI() {
+  web_ui()->GetWebState()->GetInterfaceBinderForMainFrame()->RemoveInterface(
+      "commerce_internals.mojom.CommerceInternalsHandlerFactory");
+}
+
+}  // namespace commerce