support-tool: Create DataCollector interface

Create DataCollector interface and one example implementation class,
UiHierarchyDataCollector. Create SupportToolHandler class which will
contain the list of DataCollectors and will run the functions of
DataCollectors. Add support_tool_util.cc, which will contain the
function to create SupportToolHandler and add required DataCollectors to
it, based on the data collection module requested by the user. For now,
it only creates a SupportToolHandler for Chrome OS and adds one data
collector in it. The functions are empty for now, and will be filled in
next CL. This CL only declared the function names and defined the
general workflow of the Support Tool.
For more context please see: go/support-tool-v1-design

Bug: b:200510719
Test: None for now.
Change-Id: Ia3f35262d567b82cfced96369df5c4545c8fef9e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3197152
Reviewed-by: Pavol Marko <[email protected]>
Reviewed-by: David Roger <[email protected]>
Commit-Queue: Irem Uğuz <[email protected]>
Cr-Commit-Position: refs/heads/main@{#931917}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index b305b96e..937d7d4f9 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1739,6 +1739,13 @@
     "subresource_redirect/subresource_redirect_observer.h",
     "subresource_redirect/subresource_redirect_util.cc",
     "subresource_redirect/subresource_redirect_util.h",
+    "support_tool/data_collector.h",
+    "support_tool/support_tool_handler.cc",
+    "support_tool/support_tool_handler.h",
+    "support_tool/support_tool_util.cc",
+    "support_tool/support_tool_util.h",
+    "support_tool/ui_hierarchy_data_collector.cc",
+    "support_tool/ui_hierarchy_data_collector.h",
     "sync/bookmark_sync_service_factory.cc",
     "sync/bookmark_sync_service_factory.h",
     "sync/chrome_sync_client.cc",
diff --git a/chrome/browser/support_tool/DIR_METADATA b/chrome/browser/support_tool/DIR_METADATA
new file mode 100644
index 0000000..9327e8d
--- /dev/null
+++ b/chrome/browser/support_tool/DIR_METADATA
@@ -0,0 +1,3 @@
+buganizer: {
+  component_id: 1111615
+}
diff --git a/chrome/browser/support_tool/OWNERS b/chrome/browser/support_tool/OWNERS
new file mode 100644
index 0000000..63381752
--- /dev/null
+++ b/chrome/browser/support_tool/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/chrome/browser/support_tool/data_collector.h b/chrome/browser/support_tool/data_collector.h
new file mode 100644
index 0000000..93a50fad
--- /dev/null
+++ b/chrome/browser/support_tool/data_collector.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPPORT_TOOL_DATA_COLLECTOR_H_
+#define CHROME_BROWSER_SUPPORT_TOOL_DATA_COLLECTOR_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+
+// PII (Personally Identifiable Information) types that can exist in the debug
+// data and logs DataCollector collects.
+enum class PIIType {
+  // Window titles that appear in UI hierarchy.
+  kUIHierarchyWindowTitles,
+};
+
+using PIIMap = std::multimap<PIIType, std::string>;
+
+// The DataCollector provides an interface for data sources that the
+// SupportToolHandler uses to collect debug data from multiple sources in Chrome
+// or Chrome OS with Support Tool.
+class DataCollector {
+ public:
+  virtual ~DataCollector() = default;
+
+  // Returns a url-encodable name of this DataCollector.
+  virtual std::string GetName() const = 0;
+
+  // Returns a user-readable description of what this DataCollector does.
+  virtual std::string GetDescription() const = 0;
+
+  // Returns the detected PII in the collected data.
+  virtual const PIIMap& GetDetectedPII() = 0;
+
+  // Collects all data that can be collected and detects the PII in the
+  // collected data.
+  virtual void CollectDataAndDetectPII(
+      base::OnceClosure on_data_collected_callback) = 0;
+};
+
+#endif  // CHROME_BROWSER_SUPPORT_TOOL_DATA_COLLECTOR_H_
diff --git a/chrome/browser/support_tool/support_tool_handler.cc b/chrome/browser/support_tool/support_tool_handler.cc
new file mode 100644
index 0000000..2ff927c
--- /dev/null
+++ b/chrome/browser/support_tool/support_tool_handler.cc
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/support_tool/support_tool_handler.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/check.h"
+#include "chrome/browser/support_tool/data_collector.h"
+
+SupportToolHandler::SupportToolHandler() = default;
+SupportToolHandler::~SupportToolHandler() = default;
+
+void SupportToolHandler::AddDataCollector(
+    std::unique_ptr<DataCollector> collector) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(collector);
+  data_collectors_.emplace_back(std::move(collector));
+}
+
+void SupportToolHandler::CollectSupportData(
+    SupportToolDataCollectedCallback on_data_collection_done_callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!on_data_collection_done_callback.is_null());
+  DCHECK(!data_collectors_.empty());
+
+  on_data_collection_done_callback_ =
+      std::move(on_data_collection_done_callback);
+
+  base::RepeatingClosure collect_data_barrier_closure = base::BarrierClosure(
+      data_collectors_.size(),
+      base::BindOnce(&SupportToolHandler::OnAllDataCollected,
+                     weak_ptr_factory_.GetWeakPtr()));
+
+  for (auto& data_collector : data_collectors_) {
+    data_collector->CollectDataAndDetectPII(base::BindOnce(
+        &SupportToolHandler::OnDataCollected, weak_ptr_factory_.GetWeakPtr(),
+        collect_data_barrier_closure));
+  }
+}
+
+void SupportToolHandler::OnDataCollected(
+    base::RepeatingClosure barrier_closure) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  std::move(barrier_closure).Run();
+}
+
+void SupportToolHandler::OnAllDataCollected() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (auto& data_collector : data_collectors_) {
+    const PIIMap& collected = data_collector->GetDetectedPII();
+    // Use std::multipmap.merge() function after migration to C++17.
+    detected_pii_.insert(collected.begin(), collected.end());
+  }
+  std::move(on_data_collection_done_callback_).Run(detected_pii_);
+}
diff --git a/chrome/browser/support_tool/support_tool_handler.h b/chrome/browser/support_tool/support_tool_handler.h
new file mode 100644
index 0000000..0323184
--- /dev/null
+++ b/chrome/browser/support_tool/support_tool_handler.h
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_HANDLER_H_
+#define CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_HANDLER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "chrome/browser/support_tool/data_collector.h"
+
+using SupportToolDataCollectedCallback =
+    base::OnceCallback<void(const PIIMap&)>;
+
+// The SupportToolHandler collects debug data from a list of DataCollectors.
+//
+// EXAMPLE:
+// class Foo {
+//  public:
+//   void ProcessCollectedData(const PIIMap& detected) {
+//     // do something with the detected PII.
+//   }
+//   void GetSupportData() {
+//     SupportToolHandler* handler = new SupportToolHandler();
+//     handler->AddSource(std::make_unique<DataCollectorOne>());
+//     handler->AddSource(std::make_unique<DataCollectorTwo>());
+//     handler->CollectSupportData(
+//         base::BindOnce(&Foo::ProcessCollectedData, this));
+//   }
+// };
+
+class SupportToolHandler {
+ public:
+  SupportToolHandler();
+  ~SupportToolHandler();
+
+  // Adds `collector` to the list of DataCollectors the SupportToolHandler
+  // will collect data from.
+  void AddDataCollector(std::unique_ptr<DataCollector> collector);
+
+  // Collects data from the DataCollectors added to the handler.
+  void CollectSupportData(
+      SupportToolDataCollectedCallback on_data_collection_done_callback);
+
+ private:
+  // OnDataCollected is called when a single DataCollector finished collecting
+  // data. Runs `barrier_closure` to make the handler wait until all
+  // DataCollectors finish collecting.
+  void OnDataCollected(base::RepeatingClosure barrier_closure);
+
+  // OnAllDataCollected is called by a BarrierClosure when all DataCollectors
+  // finish collecting data. Returns the detected PII by running
+  // `on_data_collection_done_callback_`.
+  void OnAllDataCollected();
+
+  SEQUENCE_CHECKER(sequence_checker_);
+  PIIMap detected_pii_;
+  std::vector<std::unique_ptr<DataCollector>> data_collectors_;
+  SupportToolDataCollectedCallback on_data_collection_done_callback_;
+  base::WeakPtrFactory<SupportToolHandler> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_HANDLER_H_
diff --git a/chrome/browser/support_tool/support_tool_handler_unittest.cc b/chrome/browser/support_tool/support_tool_handler_unittest.cc
new file mode 100644
index 0000000..f9a026c
--- /dev/null
+++ b/chrome/browser/support_tool/support_tool_handler_unittest.cc
@@ -0,0 +1,99 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/support_tool/support_tool_handler.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "chrome/browser/support_tool/data_collector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TestDataCollector implements DataCollector functions for testing.
+class TestDataCollector : public DataCollector {
+ public:
+  explicit TestDataCollector(std::string name) : DataCollector(), name_(name) {}
+  ~TestDataCollector() override = default;
+
+  // Overrides from DataCollector.
+  std::string GetName() const override { return name_; }
+
+  std::string GetDescription() const override {
+    return "The data collector that will be used for testing";
+  }
+
+  const PIIMap& GetDetectedPII() override { return pii_map_; }
+
+  void CollectDataAndDetectPII(
+      base::OnceCallback<void()> on_data_collected_callback) override {
+    // Add fake PII for testing.
+    AddPIIForTesting();
+    std::move(on_data_collected_callback).Run();
+  }
+
+ private:
+  // Adds an entry to the PIIMap with the name of the data collector. The
+  // PIIType is not significant at this point so we use a random one.
+  void AddPIIForTesting() {
+    pii_map_.insert(std::pair<PIIType, std::string>(
+        PIIType::kUIHierarchyWindowTitles, name_));
+  }
+
+  // Name of the TestDataCollector. It will be used to create fake PII inside
+  // the PIIMap.
+  std::string name_;
+  PIIMap pii_map_;
+};
+
+class SupportToolHandlerTest : public ::testing::Test {
+ public:
+  SupportToolHandlerTest() {
+    // Create and set up SupportToolHandler.
+    handler_ = std::make_unique<SupportToolHandler>();
+    SetUpHandler();
+  }
+
+  SupportToolHandlerTest(const SupportToolHandlerTest&) = delete;
+  SupportToolHandlerTest& operator=(const SupportToolHandlerTest&) = delete;
+
+  // Run SupportToolHandler's CollectSupportData and returns the result.
+  const PIIMap& CollectData() {
+    base::RunLoop run_loop;
+    handler_->CollectSupportData(
+        base::BindOnce(&SupportToolHandlerTest::OnDataCollected,
+                       base::Unretained(this), run_loop.QuitClosure()));
+    run_loop.Run();
+    return pii_result_;
+  }
+
+ private:
+  // Adds TestDataCollectors to SupportToolHandler.
+  void SetUpHandler() {
+    handler_->AddDataCollector(
+        std::make_unique<TestDataCollector>("test_data_collector_1"));
+    handler_->AddDataCollector(
+        std::make_unique<TestDataCollector>("test_data_collector_2"));
+  }
+
+  void OnDataCollected(base::OnceClosure quit_closure, const PIIMap& result) {
+    pii_result_ = result;
+    std::move(quit_closure).Run();
+  }
+
+  std::unique_ptr<SupportToolHandler> handler_;
+  PIIMap pii_result_;
+};
+
+TEST_F(SupportToolHandlerTest, CollectSupportData) {
+  base::test::TaskEnvironment task_environment;
+
+  const PIIMap& detected_pii = CollectData();
+  // Check if the detected PII map returned from the SupportToolHandler is
+  // empty.
+  EXPECT_FALSE(detected_pii.empty());
+}
diff --git a/chrome/browser/support_tool/support_tool_util.cc b/chrome/browser/support_tool/support_tool_util.cc
new file mode 100644
index 0000000..1d013aca7
--- /dev/null
+++ b/chrome/browser/support_tool/support_tool_util.cc
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/support_tool/support_tool_util.h"
+
+#include <memory>
+
+#include "chrome/browser/support_tool/support_tool_handler.h"
+#include "chrome/browser/support_tool/ui_hierarchy_data_collector.h"
+
+std::unique_ptr<SupportToolHandler> GetSupportToolHandler(bool chrome_os,
+                                                          bool chrome_browser) {
+  std::unique_ptr<SupportToolHandler> handler =
+      std::make_unique<SupportToolHandler>();
+  if (chrome_os) {
+    handler->AddDataCollector(std::make_unique<UiHierarchyDataCollector>());
+  }
+  return handler;
+}
diff --git a/chrome/browser/support_tool/support_tool_util.h b/chrome/browser/support_tool/support_tool_util.h
new file mode 100644
index 0000000..a70d1ee5
--- /dev/null
+++ b/chrome/browser/support_tool/support_tool_util.h
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_
+#define CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_
+
+#include "chrome/browser/support_tool/support_tool_handler.h"
+
+// Returns SupportToolHandler that is created for collecting logs from the
+// given data modules. Adds all Chrome OS related DataCollectors to the
+// SupportToolHandler if `chrome_os` is true. Adds all Chrome browser
+// DataCollectors if `chrome_browser` is true.
+std::unique_ptr<SupportToolHandler> GetSupportToolHandler(bool chrome_os,
+                                                          bool chrome_browser);
+
+#endif  // CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_
diff --git a/chrome/browser/support_tool/ui_hierarchy_data_collector.cc b/chrome/browser/support_tool/ui_hierarchy_data_collector.cc
new file mode 100644
index 0000000..8cebe8f
--- /dev/null
+++ b/chrome/browser/support_tool/ui_hierarchy_data_collector.cc
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/support_tool/ui_hierarchy_data_collector.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "chrome/browser/support_tool/data_collector.h"
+
+UiHierarchyDataCollector::UiHierarchyDataCollector() = default;
+UiHierarchyDataCollector::~UiHierarchyDataCollector() = default;
+
+std::string UiHierarchyDataCollector::GetName() const {
+  return "UI Hierarchy";
+}
+
+std::string UiHierarchyDataCollector::GetDescription() const {
+  return "Collects UI hiearchy data.";
+}
+
+const PIIMap& UiHierarchyDataCollector::GetDetectedPII() {
+  return pii_map_;
+}
+
+void UiHierarchyDataCollector::CollectDataAndDetectPII(
+    base::OnceCallback<void()> on_data_collected_callback) {
+  // This function Will be filled later.
+  // Data will be collected and this.pii_map_ will be filled here.
+  base::ThreadPool::PostTask(
+      FROM_HERE, base::BindOnce(std::move(on_data_collected_callback)));
+}
diff --git a/chrome/browser/support_tool/ui_hierarchy_data_collector.h b/chrome/browser/support_tool/ui_hierarchy_data_collector.h
new file mode 100644
index 0000000..fc018ff
--- /dev/null
+++ b/chrome/browser/support_tool/ui_hierarchy_data_collector.h
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPPORT_TOOL_UI_HIERARCHY_DATA_COLLECTOR_H_
+#define CHROME_BROWSER_SUPPORT_TOOL_UI_HIERARCHY_DATA_COLLECTOR_H_
+
+#include "base/callback_forward.h"
+#include "chrome/browser/support_tool/data_collector.h"
+
+class UiHierarchyDataCollector : public DataCollector {
+ public:
+  UiHierarchyDataCollector();
+  ~UiHierarchyDataCollector() override;
+
+  // Overrides from DataCollector.
+  std::string GetName() const override;
+
+  std::string GetDescription() const override;
+
+  const PIIMap& GetDetectedPII() override;
+
+  void CollectDataAndDetectPII(
+      base::OnceCallback<void()> on_data_collected_callback) override;
+
+ private:
+  PIIMap pii_map_;
+};
+
+#endif  // CHROME_BROWSER_SUPPORT_TOOL_UI_HIERARCHY_DATA_COLLECTOR_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b42ef3d..2904494 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4692,6 +4692,7 @@
     "../browser/subresource_redirect/litepages_service_bypass_decider_unittest.cc",
     "../browser/subresource_redirect/origin_robots_rules_unittest.cc",
     "../browser/subresource_redirect/subresource_redirect_util_unit_test.cc",
+    "../browser/support_tool/support_tool_handler_unittest.cc",
     "../browser/ui/autofill/payments/offer_notification_helper_unittest.cc",
 
     # TODO(hashimoto): those tests should be componentized and moved to