[fuchsia] Adds a singleton to access inspect root node. (#25745)

Bug:  fxbug.dev/75281
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 4c361ac..8833bbd 100755
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1373,6 +1373,8 @@
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.cc
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.h
+FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.cc
+FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.h
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h
 FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc
diff --git a/shell/platform/fuchsia/dart_runner/main.cc b/shell/platform/fuchsia/dart_runner/main.cc
index ff72073..b652bc5 100644
--- a/shell/platform/fuchsia/dart_runner/main.cc
+++ b/shell/platform/fuchsia/dart_runner/main.cc
@@ -15,6 +15,7 @@
 #include "logging.h"
 #include "platform/utils.h"
 #include "runtime/dart/utils/files.h"
+#include "runtime/dart/utils/root_inspect_node.h"
 #include "runtime/dart/utils/tempfs.h"
 #include "third_party/dart/runtime/include/dart_api.h"
 
@@ -37,11 +38,10 @@
 
   // Create our component context which is served later.
   auto context = sys::ComponentContext::Create();
-  sys::ComponentInspector inspector(context.get());
+  dart_utils::RootInspectNode::Initialize(context.get());
 
-  inspect::Node& root = inspector.inspector()->GetRoot();
-
-  dart::SetDartVmNode(std::make_unique<inspect::Node>(root.CreateChild("vm")));
+  dart::SetDartVmNode(std::make_unique<inspect::Node>(
+      dart_utils::RootInspectNode::CreateRootChild("vm")));
 
   std::unique_ptr<trace::TraceProviderWithFdio> provider;
   {
diff --git a/shell/platform/fuchsia/flutter/main.cc b/shell/platform/fuchsia/flutter/main.cc
index bb40bbe..3b0fae8 100644
--- a/shell/platform/fuchsia/flutter/main.cc
+++ b/shell/platform/fuchsia/flutter/main.cc
@@ -12,6 +12,7 @@
 #include "loop.h"
 #include "platform/utils.h"
 #include "runner.h"
+#include "runtime/dart/utils/root_inspect_node.h"
 #include "runtime/dart/utils/tempfs.h"
 
 int main(int argc, char const* argv[]) {
@@ -19,13 +20,12 @@
 
   // Create our component context which is served later.
   auto context = sys::ComponentContext::Create();
-  sys::ComponentInspector inspector(context.get());
-
-  inspect::Node& root = inspector.inspector()->GetRoot();
+  dart_utils::RootInspectNode::Initialize(context.get());
 
   // We inject the 'vm' node into the dart vm so that it can add any inspect
   // data that it needs to the inspect tree.
-  dart::SetDartVmNode(std::make_unique<inspect::Node>(root.CreateChild("vm")));
+  dart::SetDartVmNode(std::make_unique<inspect::Node>(
+      dart_utils::RootInspectNode::CreateRootChild("vm")));
 
   std::unique_ptr<trace::TraceProviderWithFdio> provider;
   {
diff --git a/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn
index ecbfb0e..e2505c6 100644
--- a/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn
+++ b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn
@@ -22,6 +22,8 @@
       "logging.h",
       "mapped_resource.cc",
       "mapped_resource.h",
+      "root_inspect_node.cc",
+      "root_inspect_node.h",
       "tempfs.cc",
       "tempfs.h",
       "vmo.cc",
@@ -39,6 +41,7 @@
              "$fuchsia_sdk_root/pkg:fdio",
              "$fuchsia_sdk_root/pkg:memfs",
              "$fuchsia_sdk_root/pkg:sys_cpp",
+             "$fuchsia_sdk_root/pkg:sys_inspect_cpp",
              "$fuchsia_sdk_root/pkg:syslog",
              "$fuchsia_sdk_root/pkg:trace",
              "$fuchsia_sdk_root/pkg:vfs_cpp",
diff --git a/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.cc b/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.cc
new file mode 100644
index 0000000..8909916
--- /dev/null
+++ b/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.cc
@@ -0,0 +1,24 @@
+// Copyright 2013 The Flutter 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 "root_inspect_node.h"
+
+namespace dart_utils {
+
+std::unique_ptr<sys::ComponentInspector> RootInspectNode::inspector_;
+std::mutex RootInspectNode::mutex_;
+
+void RootInspectNode::Initialize(sys::ComponentContext* context) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  if (!inspector_) {
+    inspector_ = std::make_unique<sys::ComponentInspector>(context);
+  }
+}
+
+inspect::Node RootInspectNode::CreateRootChild(const std::string& name) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  return inspector_->inspector()->GetRoot().CreateChild(name);
+}
+
+}  // namespace dart_utils
diff --git a/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.h b/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.h
new file mode 100644
index 0000000..951985a
--- /dev/null
+++ b/shell/platform/fuchsia/runtime/dart/utils/root_inspect_node.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_ROOT_INSPECT_NODE_H_
+#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_ROOT_INSPECT_NODE_H_
+
+#include <lib/sys/inspect/cpp/component.h>
+
+#include <memory>
+#include <mutex>
+
+namespace dart_utils {
+
+// This singleton object offers a way to create a new inspect node under the
+// root node in a thread safe way.
+//
+// Usage notes:
+// RootInspectNode::Initialize() must  be invoked once in the program's
+// main before trying to obtain a  child node.
+class RootInspectNode {
+ private:
+  RootInspectNode() = default;
+  ~RootInspectNode() = default;
+
+ public:
+  // Initializes the underlying component inspector. Must be invoked at least
+  // once before calling CreateRootChild().
+  static void Initialize(sys::ComponentContext* context);
+
+  // Creates an inspect node which is a child of the component's root inspect
+  // node with the provided |name|.
+  static inspect::Node CreateRootChild(const std::string& name);
+
+ private:
+  static std::unique_ptr<sys::ComponentInspector> inspector_;
+  static std::mutex mutex_;
+};
+
+}  // namespace dart_utils
+
+#endif  // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_ROOT_INSPECT_NODE_H_