Enable Heap Profiling Service in Chromecast

Hook up heap_profiling::Supervisor in browser process in cast_shell
so that it can access the heap profiling process.

Bug=Internal b/110433621

Change-Id: I59fdad131108955a8a87f3ba2050664c5f294941
Reviewed-on: https://chromium-review.googlesource.com/c/1282042
Commit-Queue: Chia-hung Duan <chiahungduan@google.com>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Erik Chen <erikchen@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Luke Halliwell <halliwell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#617038}
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index f40e06f..7b586eb 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -142,9 +142,11 @@
     "//chromecast/net",
     "//chromecast/service",
     "//components/download/public/common:public",
+    "//components/heap_profiling",
     "//components/metrics",
     "//components/metrics:gpu",
     "//components/metrics:net",
+    "//components/services/heap_profiling/public/mojom",
 
     # TODO(gfhuang): Eliminate this dependency if ScreenInfoMetricsProvider
     # isn't needed. crbug.com/541577
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS
index 9c992f3..4f95459 100644
--- a/chromecast/browser/DEPS
+++ b/chromecast/browser/DEPS
@@ -10,12 +10,14 @@
   "+components/cdm/browser",
   "+components/crash",
   "+components/download/public/common",
+  "+components/heap_profiling",
   "+components/keyed_service",
   "+components/network_hints/browser",
   "+components/network_session_configurator/common",
   "+components/prefs",
   "+components/pref_registry",
   "+components/proxy_config",
+  "+components/services/heap_profiling/public/mojom",
   "+components/storage_monitor",
   "+components/user_prefs",
   "+components/version_info",
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 2a53c8d..7e23801 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
@@ -52,6 +53,8 @@
 #include "chromecast/net/connectivity_checker.h"
 #include "chromecast/public/cast_media_shlib.h"
 #include "chromecast/service/cast_service.h"
+#include "components/heap_profiling/client_connection_manager.h"
+#include "components/heap_profiling/supervisor.h"
 #include "components/prefs/pref_service.h"
 #include "components/viz/common/switches.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -218,6 +221,14 @@
 
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
+std::unique_ptr<heap_profiling::ClientConnectionManager>
+CreateClientConnectionManager(
+    base::WeakPtr<heap_profiling::Controller> controller_weak_ptr,
+    heap_profiling::Mode mode) {
+  return std::make_unique<heap_profiling::ClientConnectionManager>(
+      std::move(controller_weak_ptr), mode);
+}
+
 }  // namespace
 
 namespace chromecast {
@@ -677,5 +688,14 @@
 #endif  // !defined(OS_ANDROID)
 }
 
+void CastBrowserMainParts::ServiceManagerConnectionStarted(
+    content::ServiceManagerConnection* connection) {
+  heap_profiling::Supervisor* supervisor =
+      heap_profiling::Supervisor::GetInstance();
+  supervisor->SetClientConnectionManagerConstructor(
+      &CreateClientConnectionManager);
+  supervisor->Start(connection, base::NullCallback());
+}
+
 }  // namespace shell
 }  // namespace chromecast
diff --git a/chromecast/browser/cast_browser_main_parts.h b/chromecast/browser/cast_browser_main_parts.h
index 662b5d4..4f63d5a 100644
--- a/chromecast/browser/cast_browser_main_parts.h
+++ b/chromecast/browser/cast_browser_main_parts.h
@@ -84,6 +84,10 @@
   void PostDestroyThreads() override;
 
  private:
+  // content::BrowserMainParts implementation:
+  void ServiceManagerConnectionStarted(
+      content::ServiceManagerConnection* connection) override;
+
   std::unique_ptr<CastBrowserProcess> cast_browser_process_;
   const content::MainFunctionParams parameters_;  // For running browser tests.
   // Caches a pointer of the CastContentBrowserClient.
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 0b2dca79..d8e67694 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -53,6 +53,7 @@
 #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
 #include "chromecast/public/media/media_pipeline_backend.h"
 #include "components/network_hints/browser/network_hints_message_filter.h"
+#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/certificate_request_result_type.h"
@@ -886,5 +887,12 @@
   return chromecast::shell::GetUserAgent();
 }
 
+void CastContentBrowserClient::RegisterOutOfProcessServices(
+    OutOfProcessServiceMap* services) {
+  services->emplace(
+      heap_profiling::mojom::kServiceName,
+      base::BindRepeating(&base::ASCIIToUTF16, "Profiling Service"));
+}
+
 }  // namespace shell
 }  // namespace chromecast
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 30fe3ff..83c0e938 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -200,6 +200,7 @@
   std::vector<std::unique_ptr<content::NavigationThrottle>>
   CreateThrottlesForNavigation(content::NavigationHandle* handle) override;
   std::string GetUserAgent() const override;
+  void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override;
   CastFeatureListCreator* GetCastFeatureListCreator() {
     return cast_feature_list_creator_;
   }
diff --git a/chromecast/browser/cast_content_browser_manifest_overlay.json b/chromecast/browser/cast_content_browser_manifest_overlay.json
index 27716745..8969c7c 100644
--- a/chromecast/browser/cast_content_browser_manifest_overlay.json
+++ b/chromecast/browser/cast_content_browser_manifest_overlay.json
@@ -3,6 +3,12 @@
   "display_name": "Cast Shell (Browser)",
   "interface_provider_specs": {
     "service_manager:connector": {
+      "requires": {
+        "heap_profiling" : [
+          "profiling",
+          "heap_profiler"
+        ]
+      },
       "provides": {
         "renderer": [
           "chromecast.media.mojom.MediaCaps",
diff --git a/chromecast/browser/cast_content_renderer_manifest_overlay.json b/chromecast/browser/cast_content_renderer_manifest_overlay.json
index 8194a7d..2d5bb993 100644
--- a/chromecast/browser/cast_content_renderer_manifest_overlay.json
+++ b/chromecast/browser/cast_content_renderer_manifest_overlay.json
@@ -2,6 +2,11 @@
   "display_name": "Cast Renderer",
   "name": "content_renderer",
   "interface_provider_specs": {
+    "service_manager:connector": {
+      "provides": {
+        "browser": [ "heap_profiling.mojom.ProfilingClient" ]
+      }
+    },
     "navigation:frame": {
       "provides": {
         "browser": ["chromecast.shell.mojom.MediaPlaybackOptions"]
diff --git a/chromecast/common/BUILD.gn b/chromecast/common/BUILD.gn
index dac6096..d6f9c1b 100644
--- a/chromecast/common/BUILD.gn
+++ b/chromecast/common/BUILD.gn
@@ -20,6 +20,7 @@
     "//chromecast/base",
     "//chromecast/base:cast_version",
     "//chromecast/common/media",
+    "//components/services/heap_profiling/public/cpp",
     "//content/public/common",
     "//ui/base",
     "//ui/gfx",
diff --git a/chromecast/common/DEPS b/chromecast/common/DEPS
index 288eeae..9dcc12d 100644
--- a/chromecast/common/DEPS
+++ b/chromecast/common/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/services/heap_profiling/public/cpp",
   "+components/version_info",
   "+content/public/common",
   "+extensions/common",
@@ -6,6 +7,7 @@
   "+extensions/shell/common/api",
   "+extensions/shell/grit",
   "+mojo/public/cpp/bindings",
+  "+services/service_manager/public/cpp",
   "+ui/accessibility",
   "+ui/base",
   "+ui/gfx",
diff --git a/chromecast/common/cast_content_client.cc b/chromecast/common/cast_content_client.cc
index ed1ce6670..cdb783c 100644
--- a/chromecast/common/cast_content_client.cc
+++ b/chromecast/common/cast_content_client.cc
@@ -6,13 +6,18 @@
 
 #include <stdint.h>
 
+#include "base/no_destructor.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "build/build_config.h"
 #include "chromecast/base/cast_constants.h"
 #include "chromecast/base/version.h"
 #include "chromecast/chromecast_buildflags.h"
+#include "components/services/heap_profiling/public/cpp/client.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/simple_connection_filter.h"
 #include "content/public/common/user_agent.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "url/url_util.h"
@@ -130,5 +135,18 @@
 }
 #endif  // OS_ANDROID
 
+void CastContentClient::OnServiceManagerConnected(
+    content::ServiceManagerConnection* connection) {
+  static base::NoDestructor<heap_profiling::Client> profiling_client;
+
+  std::unique_ptr<service_manager::BinderRegistry> registry(
+      std::make_unique<service_manager::BinderRegistry>());
+  registry->AddInterface(
+      base::BindRepeating(&heap_profiling::Client::BindToInterface,
+                          base::Unretained(profiling_client.get())));
+  connection->AddConnectionFilter(
+      std::make_unique<content::SimpleConnectionFilter>(std::move(registry)));
+}
+
 }  // namespace shell
 }  // namespace chromecast
diff --git a/chromecast/common/cast_content_client.h b/chromecast/common/cast_content_client.h
index 2e84342..3f71712 100644
--- a/chromecast/common/cast_content_client.h
+++ b/chromecast/common/cast_content_client.h
@@ -30,6 +30,8 @@
 #if defined(OS_ANDROID)
   ::media::MediaDrmBridgeClient* GetMediaDrmBridgeClient() override;
 #endif  // OS_ANDROID
+  void OnServiceManagerConnected(
+      content::ServiceManagerConnection* connection) override;
 };
 
 }  // namespace shell
diff --git a/chromecast/utility/BUILD.gn b/chromecast/utility/BUILD.gn
index a9e2938..15fa4f4 100644
--- a/chromecast/utility/BUILD.gn
+++ b/chromecast/utility/BUILD.gn
@@ -6,12 +6,17 @@
 
 cast_source_set("utility") {
   sources = [
+    "cast_content_utility_client.cc",
     "cast_content_utility_client.h",
   ]
 
   deps = [
     "//base",
+    "//chromecast:chromecast_buildflags",
+    "//components/services/heap_profiling",
+    "//components/services/heap_profiling/public/mojom",
     "//content/public/utility",
+    "//services/service_manager/public/cpp",
   ]
 
   if (chromecast_branding == "public") {
diff --git a/chromecast/utility/DEPS b/chromecast/utility/DEPS
index 8ad521e..6ab23ad 100644
--- a/chromecast/utility/DEPS
+++ b/chromecast/utility/DEPS
@@ -1,3 +1,5 @@
 include_rules = [
+  "+components/services/heap_profiling",
+  "+components/services/heap_profiling/public/mojom",
   "+content/public/utility",
 ]
diff --git a/chromecast/utility/cast_content_utility_client.cc b/chromecast/utility/cast_content_utility_client.cc
new file mode 100644
index 0000000..dac5c7a
--- /dev/null
+++ b/chromecast/utility/cast_content_utility_client.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 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 "chromecast/utility/cast_content_utility_client.h"
+
+#include "base/callback_forward.h"
+#include "components/services/heap_profiling/heap_profiling_service.h"
+#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
+#include "content/public/utility/utility_thread.h"
+
+namespace {
+
+std::unique_ptr<service_manager::Service> CreateHeapProfilingService(
+    service_manager::mojom::ServiceRequest request) {
+  return std::make_unique<heap_profiling::HeapProfilingService>(
+      std::move(request));
+}
+
+using ServiceFactory =
+    base::OnceCallback<std::unique_ptr<service_manager::Service>()>;
+void RunServiceOnIOThread(ServiceFactory factory) {
+  base::OnceClosure terminate_process = base::BindOnce(
+      base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
+      base::SequencedTaskRunnerHandle::Get(), FROM_HERE,
+      base::BindOnce([] { content::UtilityThread::Get()->ReleaseProcess(); }));
+  content::ChildThread::Get()->GetIOTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](ServiceFactory factory, base::OnceClosure terminate_process) {
+            service_manager::Service::RunAsyncUntilTermination(
+                std::move(factory).Run(), std::move(terminate_process));
+          },
+          std::move(factory), std::move(terminate_process)));
+}
+
+}  // namespace
+
+namespace chromecast {
+namespace shell {
+
+bool CastContentUtilityClient::HandleServiceRequest(
+    const std::string& service_name,
+    service_manager::mojom::ServiceRequest request) {
+  if (service_name == heap_profiling::mojom::kServiceName) {
+    RunServiceOnIOThread(
+        base::BindOnce(&CreateHeapProfilingService, std::move(request)));
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace shell
+}  // namespace chromecast
diff --git a/chromecast/utility/cast_content_utility_client.h b/chromecast/utility/cast_content_utility_client.h
index 7f7528d..c4b67dd 100644
--- a/chromecast/utility/cast_content_utility_client.h
+++ b/chromecast/utility/cast_content_utility_client.h
@@ -19,6 +19,11 @@
 
   CastContentUtilityClient() {}
 
+  // content::ContentUtilityClient implementation:
+  bool HandleServiceRequest(
+      const std::string& service_name,
+      service_manager::mojom::ServiceRequest request) override;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CastContentUtilityClient);
 };