Tracing: Start the tracing service on-demand

Instead of each process connecting to the tracing service
on startup, the tracing service is now instead brought
up on demand (when something binds the Coordinator interface)
and will then pass pointers to the AgentRegistry and
PerfettoService to the other services so they can register themselves.

This is a prerequisite to having the tracing service run as a
sandboxed service (or we would always have a new background process
running): https://chromium-review.googlesource.com/c/chromium/src/+/1412016

Requires these prior CLs for service_manager manifest support:
* https://chromium-review.googlesource.com/c/chromium/src/+/1410124
* https://chromium-review.googlesource.com/c/chromium/src/+/1410384

TBR=yusukes@chromium.org (for trivial CrOS change)

Bug: 914579
Change-Id: Ia1c92fe2aa75e3411efbd119cb9443e8a78e4c8f
Reviewed-on: https://chromium-review.googlesource.com/c/1377593
Commit-Queue: oysteine <oysteine@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Eric Seckler <eseckler@chromium.org>
Reviewed-by: Sami Kyöstilä <skyostil@chromium.org>
Reviewed-by: Ehsan Chiniforooshan <chiniforooshan@chromium.org>
Reviewed-by: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#625059}
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
index e97cca7..6b2adab 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
@@ -450,7 +450,6 @@
           tracing::mojom::TraceDataType::ARRAY,
           base::kNullProcessId),
       bridge_(bridge) {
-  Connect(content::ServiceManagerConnection::GetForProcess()->GetConnector());
 }
 
 ArcTracingBridge::ArcTracingAgent::~ArcTracingAgent() = default;
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc
index 904de98..de8d6c5d 100644
--- a/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -662,6 +662,27 @@
 void BackgroundTracingManagerImpl::OnAbortScenarioReceived(
     std::unique_ptr<const base::DictionaryValue> metadata,
     base::RefCountedString* trace_str) {
+  if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) {
+    // Since the BackgroundTracingManager directly enables tracing
+    // in TraceLog, in addition to going through Mojo, there's an edge-case
+    // where tracing is rapidly stopped after starting, too quickly for the
+    // TraceEventAgent of the browser process to register itself, which means
+    // that we're left in a state where the Mojo interface doesn't think we're
+    // tracing but TraceLog is still enabled. If that's the case, we abort
+    // tracing here.
+    auto record_mode =
+        (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE)
+            ? base::trace_event::RECORD_CONTINUOUSLY
+            : base::trace_event::RECORD_UNTIL_FULL;
+    TraceConfig config =
+        GetConfigForCategoryPreset(config_->category_preset(), record_mode);
+
+    uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE;
+    if (!config.event_filters().empty())
+      modes |= base::trace_event::TraceLog::FILTERING_MODE;
+    base::trace_event::TraceLog::GetInstance()->SetDisabled(modes);
+  }
+
   is_tracing_ = false;
   triggered_named_event_handle_ = -1;
   config_.reset();
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc
index d59699d3..3abe338 100644
--- a/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -129,6 +129,29 @@
   }
 };
 
+class WaitForTraceLogEnabled
+    : public base::trace_event::TraceLog::EnabledStateObserver {
+ public:
+  WaitForTraceLogEnabled() {
+    base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+  }
+
+  ~WaitForTraceLogEnabled() override {
+    base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
+        this);
+  }
+
+  void Wait() { wait_for_tracelog_.Run(); }
+
+  // TraceLog::EnabledStateObserver overrides:
+  void OnTraceLogEnabled() override { wait_for_tracelog_.Quit(); }
+
+  void OnTraceLogDisabled() override {}
+
+ private:
+  base::RunLoop wait_for_tracelog_;
+};
+
 class TracingControllerTest : public ContentBrowserTest {
  public:
   TracingControllerTest() {}
@@ -222,9 +245,11 @@
       TraceConfig config;
       if (enable_systrace)
         config.EnableSystrace();
+      WaitForTraceLogEnabled wait_for_tracelog;
       bool result = controller->StartTracing(config, std::move(callback));
       ASSERT_TRUE(result);
       run_loop.Run();
+      wait_for_tracelog.Wait();
       EXPECT_EQ(enable_recording_done_callback_count(), 1);
     }
 
@@ -266,9 +291,11 @@
       TraceConfig config = TraceConfig();
       config.EnableArgumentFilter();
 
+      WaitForTraceLogEnabled wait_for_tracelog;
       bool result = controller->StartTracing(config, std::move(callback));
       ASSERT_TRUE(result);
       run_loop.Run();
+      wait_for_tracelog.Wait();
       EXPECT_EQ(enable_recording_done_callback_count(), 1);
     }
 
@@ -305,10 +332,12 @@
       TracingController::StartTracingDoneCallback callback =
           base::BindOnce(&TracingControllerTest::StartTracingDoneCallbackTest,
                          base::Unretained(this), run_loop.QuitClosure());
+      WaitForTraceLogEnabled wait_for_tracelog;
       bool result =
           controller->StartTracing(TraceConfig(), std::move(callback));
       ASSERT_TRUE(result);
       run_loop.Run();
+      wait_for_tracelog.Wait();
       EXPECT_EQ(enable_recording_done_callback_count(), 1);
     }
 
@@ -340,10 +369,12 @@
       TracingController::StartTracingDoneCallback callback =
           base::BindOnce(&TracingControllerTest::StartTracingDoneCallbackTest,
                          base::Unretained(this), run_loop.QuitClosure());
+      WaitForTraceLogEnabled wait_for_tracelog;
       bool result =
           controller->StartTracing(TraceConfig(), std::move(callback));
       ASSERT_TRUE(result);
       run_loop.Run();
+      wait_for_tracelog.Wait();
       EXPECT_EQ(enable_recording_done_callback_count(), 1);
     }
 
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
index 994119b..2216fde 100644
--- a/content/browser/tracing/tracing_controller_impl.cc
+++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -35,6 +35,7 @@
 #include "net/base/network_change_notifier.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/tracing/public/cpp/trace_event_agent.h"
+#include "services/tracing/public/cpp/traced_process.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 #include "v8/include/v8-version-string.h"
 
@@ -127,9 +128,8 @@
 TracingControllerImpl::~TracingControllerImpl() = default;
 
 void TracingControllerImpl::AddAgents() {
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(tracing::mojom::kServiceName, &coordinator_);
+  tracing::TracedProcess::GetInstance()->SetTaskRunner(
+      base::SequencedTaskRunnerHandle::Get());
 
 #if defined(OS_CHROMEOS)
   agents_.push_back(std::make_unique<CrOSTracingAgent>());
@@ -137,14 +137,9 @@
   agents_.push_back(std::make_unique<CastTracingAgent>());
 #endif
 
-  for (auto& agent : agents_)
-    agent->Connect(connector);
-
-  auto* trace_event_agent = tracing::TraceEventAgent::GetInstance();
-  trace_event_agent->Connect(connector);
-
   // For adding general CPU, network, OS, and other system information to the
   // metadata.
+  auto* trace_event_agent = tracing::TraceEventAgent::GetInstance();
   trace_event_agent->AddMetadataGeneratorFunction(base::BindRepeating(
       &TracingControllerImpl::GenerateMetadataDict, base::Unretained(this)));
   if (delegate_) {
@@ -154,6 +149,18 @@
   }
 }
 
+void TracingControllerImpl::ConnectToServiceIfNeeded() {
+  if (!coordinator_) {
+    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
+        tracing::mojom::kServiceName, &coordinator_);
+  }
+}
+
+void TracingControllerImpl::DisconnectFromService() {
+  coordinator_ = nullptr;
+}
+
+// Can be called on any thread.
 std::unique_ptr<base::DictionaryValue>
 TracingControllerImpl::GenerateMetadataDict() const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -319,6 +326,8 @@
   }
   trace_config_ =
       std::make_unique<base::trace_event::TraceConfig>(trace_config);
+
+  ConnectToServiceIfNeeded();
   coordinator_->StartTracing(
       trace_config.ToString(),
       base::BindOnce(
@@ -376,6 +385,7 @@
     GetTraceBufferUsageCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
+  ConnectToServiceIfNeeded();
   coordinator_->RequestBufferUsage(base::BindOnce(
       [](GetTraceBufferUsageCallback callback, bool success, float percent_full,
          uint32_t approximate_count) {
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h
index 4d7434a..dbb0b86 100644
--- a/content/browser/tracing/tracing_controller_impl.h
+++ b/content/browser/tracing/tracing_controller_impl.h
@@ -75,6 +75,8 @@
 
   ~TracingControllerImpl() override;
   void AddAgents();
+  void ConnectToServiceIfNeeded();
+  void DisconnectFromService();
   std::unique_ptr<base::DictionaryValue> GenerateMetadataDict() const;
 
   // mojo::DataPipeDrainer::Client
@@ -85,7 +87,6 @@
 
   void CompleteFlush();
 
-  tracing::mojom::AgentRegistryPtr agent_registry_;
   tracing::mojom::CoordinatorPtr coordinator_;
   std::vector<std::unique_ptr<tracing::BaseAgent>> agents_;
   std::unique_ptr<TracingDelegate> delegate_;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index a0cd22fd..754533a 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -71,7 +71,6 @@
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/runner/common/client_util.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
-#include "services/tracing/public/cpp/trace_event_agent.h"
 
 #if defined(OS_POSIX)
 #include "base/posix/global_descriptors.h"
@@ -571,8 +570,6 @@
 
   channel_->AddFilter(new tracing::ChildTraceMessageFilter(
       ChildProcess::current()->io_task_runner()));
-
-  tracing::TraceEventAgent::GetInstance()->Connect(GetConnector());
 }
 
 ChildThreadImpl::~ChildThreadImpl() {
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index a4792c9..6930f39 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -181,7 +181,7 @@
 
   void Init(const Options& options);
 
-  // Sets chrome_trace_event_agent_ if necessary.
+  // Initializes tracing if necessary.
   void InitTracing();
 
   // We create the channel first without connecting it so we can add filters
diff --git a/services/service_manager/public/cpp/BUILD.gn b/services/service_manager/public/cpp/BUILD.gn
index 08524d3..5b06500e 100644
--- a/services/service_manager/public/cpp/BUILD.gn
+++ b/services/service_manager/public/cpp/BUILD.gn
@@ -42,6 +42,14 @@
     "//url",
   ]
 
+  deps = [
+    "//services/tracing/public/mojom",
+  ]
+
+  if (!is_nacl) {
+    deps += [ "//services/tracing/public/cpp" ]
+  }
+
   defines = [
     "IS_SERVICE_MANAGER_CPP_IMPL",
 
diff --git a/services/service_manager/public/cpp/DEPS b/services/service_manager/public/cpp/DEPS
new file mode 100644
index 0000000..31137ba
--- /dev/null
+++ b/services/service_manager/public/cpp/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+services/tracing/public",
+]
diff --git a/services/service_manager/public/cpp/service_binding.cc b/services/service_manager/public/cpp/service_binding.cc
index 31a3d8d..a2b6410 100644
--- a/services/service_manager/public/cpp/service_binding.cc
+++ b/services/service_manager/public/cpp/service_binding.cc
@@ -9,7 +9,13 @@
 #include "base/bind.h"
 #include "base/no_destructor.h"
 #include "base/synchronization/lock.h"
+#include "build/build_config.h"
 #include "services/service_manager/public/cpp/service.h"
+#include "services/tracing/public/mojom/tracing.mojom.h"
+
+#if !defined(OS_NACL)
+#include "services/tracing/public/cpp/traced_process.h"
+#endif
 
 namespace service_manager {
 
@@ -166,6 +172,14 @@
     return;
   }
 
+  if (interface_name == tracing::mojom::TracedProcess::Name_) {
+#if !defined(OS_NACL)
+    tracing::TracedProcess::GetInstance()->OnTracedProcessRequest(
+        tracing::mojom::TracedProcessRequest(std::move(interface_pipe)));
+#endif
+    return;
+  }
+
   service_->OnBindInterface(source_info, interface_name,
                             std::move(interface_pipe));
 }
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn
index 7ad33670..5bb9bc0 100644
--- a/services/tracing/BUILD.gn
+++ b/services/tracing/BUILD.gn
@@ -33,6 +33,7 @@
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
+    "//services/service_manager/public/cpp",
     "//services/tracing/public/cpp",
     "//third_party/perfetto:libperfetto",
   ]
diff --git a/services/tracing/agent_registry.cc b/services/tracing/agent_registry.cc
index 5b15616..25d8209 100644
--- a/services/tracing/agent_registry.cc
+++ b/services/tracing/agent_registry.cc
@@ -74,21 +74,23 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+void AgentRegistry::DisconnectAllAgents() {
+  bindings_.CloseAllBindings();
+}
+
 void AgentRegistry::BindAgentRegistryRequest(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
-    mojom::AgentRegistryRequest request,
-    const service_manager::BindSourceInfo& source_info) {
+    mojom::AgentRegistryRequest request) {
   task_runner->PostTask(
       FROM_HERE,
       base::BindOnce(&AgentRegistry::BindAgentRegistryRequestOnSequence,
-                     base::Unretained(this), std::move(request), source_info));
+                     base::Unretained(this), std::move(request)));
 }
 
 void AgentRegistry::BindAgentRegistryRequestOnSequence(
-    mojom::AgentRegistryRequest request,
-    const service_manager::BindSourceInfo& source_info) {
+    mojom::AgentRegistryRequest request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  bindings_.AddBinding(this, std::move(request), source_info.identity);
+  bindings_.AddBinding(this, std::move(request));
 }
 
 size_t AgentRegistry::SetAgentInitializationCallback(
diff --git a/services/tracing/agent_registry.h b/services/tracing/agent_registry.h
index ba1e0e2..d87ba0ee 100644
--- a/services/tracing/agent_registry.h
+++ b/services/tracing/agent_registry.h
@@ -17,10 +17,6 @@
 #include "services/service_manager/public/cpp/identity.h"
 #include "services/tracing/public/mojom/tracing.mojom.h"
 
-namespace service_manager {
-struct BindSourceInfo;
-}  // namespace service_manager
-
 namespace tracing {
 
 class AgentRegistry : public mojom::AgentRegistry {
@@ -69,10 +65,12 @@
   AgentRegistry();
   ~AgentRegistry() override;
 
+  void DisconnectAllAgents();
+
   void BindAgentRegistryRequest(
       scoped_refptr<base::SequencedTaskRunner> task_runner,
-      mojom::AgentRegistryRequest request,
-      const service_manager::BindSourceInfo& source_info);
+      mojom::AgentRegistryRequest request);
+
   // Returns the number of existing agents that the callback was run on.
   size_t SetAgentInitializationCallback(
       const AgentInitializationCallback& callback,
@@ -91,9 +89,7 @@
   friend class AgentRegistryTest;  // For testing.
   friend class CoordinatorTest;    // For testing.
 
-  void BindAgentRegistryRequestOnSequence(
-      mojom::AgentRegistryRequest request,
-      const service_manager::BindSourceInfo& source_info);
+  void BindAgentRegistryRequestOnSequence(mojom::AgentRegistryRequest request);
 
   // mojom::AgentRegistry
   void RegisterAgent(mojom::AgentPtr agent,
@@ -103,7 +99,7 @@
 
   void UnregisterAgent(size_t agent_id);
 
-  mojo::BindingSet<mojom::AgentRegistry, service_manager::Identity> bindings_;
+  mojo::BindingSet<mojom::AgentRegistry> bindings_;
   size_t next_agent_id_ = 0;
   std::map<size_t, std::unique_ptr<AgentEntry>> agents_;
   AgentInitializationCallback agent_initialization_callback_;
diff --git a/services/tracing/coordinator.cc b/services/tracing/coordinator.cc
index 1642c2f..e3fad08 100644
--- a/services/tracing/coordinator.cc
+++ b/services/tracing/coordinator.cc
@@ -268,8 +268,10 @@
   DISALLOW_COPY_AND_ASSIGN(TraceStreamer);
 };
 
-Coordinator::Coordinator(AgentRegistry* agent_registry)
-    : binding_(this),
+Coordinator::Coordinator(AgentRegistry* agent_registry,
+                         const base::RepeatingClosure& on_disconnect_callback)
+    : on_disconnect_callback_(std::move(on_disconnect_callback)),
+      binding_(this),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
       // USER_VISIBLE because the task posted from StopAndFlushInternal() is
       // required to stop tracing from the UI.
@@ -285,6 +287,14 @@
 }
 
 Coordinator::~Coordinator() {
+  Reset();
+}
+
+bool Coordinator::IsConnected() {
+  return !!binding_;
+}
+
+void Coordinator::Reset() {
   if (!stop_and_flush_callback_.is_null()) {
     base::ResetAndReturn(&stop_and_flush_callback_)
         .Run(base::Value(base::Value::Type::DICTIONARY));
@@ -306,10 +316,17 @@
   }
 }
 
+void Coordinator::OnClientConnectionError() {
+  Reset();
+  binding_.Close();
+  on_disconnect_callback_.Run();
+}
 void Coordinator::BindCoordinatorRequest(
     mojom::CoordinatorRequest request,
     const service_manager::BindSourceInfo& source_info) {
   binding_.Bind(std::move(request));
+  binding_.set_connection_error_handler(base::BindRepeating(
+      &Coordinator::OnClientConnectionError, base::Unretained(this)));
 }
 
 void Coordinator::StartTracing(const std::string& config,
@@ -327,10 +344,12 @@
       base::BindRepeating(&Coordinator::SendStartTracingToAgent,
                           weak_ptr_factory_.GetWeakPtr()),
       false /* call_on_new_agents_only */);
-  if (!agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) {
-    std::move(callback).Run(true);
-    return;
-  }
+
+  // We specifically don't check for the case where there's
+  // no existing connected agents; meaning in that case we
+  // assume at least one *will* connect and we'll wait for
+  // it to do so and start tracing before calling the callback
+  // so that the trace will contain data from at least one agent.
   start_tracing_callback_ = std::move(callback);
 }
 
@@ -467,7 +486,7 @@
 
   maximum_trace_buffer_usage_ = 0;
   approximate_event_count_ = 0;
-  request_buffer_usage_callback_ = std::move(callback);
+
   agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) {
     agent_entry->AddDisconnectClosure(
         &kRequestBufferUsageClosureName,
@@ -479,6 +498,12 @@
         &Coordinator::OnRequestBufferStatusResponse,
         weak_ptr_factory_.GetWeakPtr(), base::Unretained(agent_entry)));
   });
+
+  if (!agent_registry_->HasDisconnectClosure(&kRequestBufferUsageClosureName)) {
+    std::move(callback).Run(true, 0.0f, 0);
+    return;
+  }
+  request_buffer_usage_callback_ = std::move(callback);
 }
 
 void Coordinator::OnRequestBufferStatusResponse(
diff --git a/services/tracing/coordinator.h b/services/tracing/coordinator.h
index f09f013c..eecae55 100644
--- a/services/tracing/coordinator.h
+++ b/services/tracing/coordinator.h
@@ -41,21 +41,28 @@
 // implement the same interface.
 class Coordinator : public mojom::Coordinator {
  public:
-  explicit Coordinator(AgentRegistry* agent_registry);
+  Coordinator(AgentRegistry* agent_registry,
+              const base::RepeatingClosure& on_disconnect_callback);
 
   void BindCoordinatorRequest(
       mojom::CoordinatorRequest request,
       const service_manager::BindSourceInfo& source_info);
 
+  bool IsConnected();
+
  protected:
   ~Coordinator() override;
 
+  virtual void OnClientConnectionError();
+
  private:
   friend std::default_delete<Coordinator>;
   friend class CoordinatorTest;  // For testing.
 
   class TraceStreamer;
 
+  void Reset();
+
   // mojom::Coordinator
   void StartTracing(const std::string& config,
                     StartTracingCallback callback) override;
@@ -82,6 +89,7 @@
                                      uint32_t capacity,
                                      uint32_t count);
 
+  base::RepeatingClosure on_disconnect_callback_;
   mojo::Binding<mojom::Coordinator> binding_;
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   const scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
diff --git a/services/tracing/coordinator_unittest.cc b/services/tracing/coordinator_unittest.cc
index 6ac773a..f986892 100644
--- a/services/tracing/coordinator_unittest.cc
+++ b/services/tracing/coordinator_unittest.cc
@@ -29,7 +29,8 @@
   // testing::Test
   void SetUp() override {
     agent_registry_ = std::make_unique<AgentRegistry>();
-    coordinator_ = std::make_unique<Coordinator>(agent_registry_.get());
+    coordinator_ = std::make_unique<Coordinator>(agent_registry_.get(),
+                                                 base::RepeatingClosure());
     output_ = "";
   }
 
@@ -341,6 +342,7 @@
 
 TEST_F(CoordinatorTest, IsTracing) {
   base::RunLoop run_loop;
+  AddArrayAgent();
   StartTracing("config", true);
   IsTracing(true);
   run_loop.RunUntilIdle();
diff --git a/services/tracing/manifest.cc b/services/tracing/manifest.cc
index eb30ff0..80af37f 100644
--- a/services/tracing/manifest.cc
+++ b/services/tracing/manifest.cc
@@ -21,15 +21,15 @@
                            .WithInstanceSharingPolicy(
                                service_manager::Manifest::
                                    InstanceSharingPolicy::kSingleton)
+                           .CanConnectToInstancesWithAnyId(true)
                            .Build())
           .ExposeCapability(
               "tracing",
               service_manager::Manifest::InterfaceList<mojom::Coordinator>())
-          .ExposeCapability("app",
-                            service_manager::Manifest::InterfaceList<
-                                mojom::AgentRegistry, mojom::PerfettoService>())
           .RequireCapability("service_manager",
                              "service_manager:service_manager")
+          .WithInterfacesBindableOnAnyService(
+              service_manager::Manifest::InterfaceList<mojom::TracedProcess>())
           .Build()};
   return *manifest;
 }
diff --git a/services/tracing/perfetto/perfetto_service.cc b/services/tracing/perfetto/perfetto_service.cc
index e4f1acc..91ad804 100644
--- a/services/tracing/perfetto/perfetto_service.cc
+++ b/services/tracing/perfetto/perfetto_service.cc
@@ -82,20 +82,15 @@
   return service_.get();
 }
 
-void PerfettoService::BindRequest(
-    mojom::PerfettoServiceRequest request,
-    const service_manager::BindSourceInfo& source_info) {
+void PerfettoService::BindRequest(mojom::PerfettoServiceRequest request) {
   perfetto_task_runner_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PerfettoService::BindOnSequence, base::Unretained(this),
-                     std::move(request), source_info.identity));
+      FROM_HERE, base::BindOnce(&PerfettoService::BindOnSequence,
+                                base::Unretained(this), std::move(request)));
 }
 
-void PerfettoService::BindOnSequence(
-    mojom::PerfettoServiceRequest request,
-    const service_manager::Identity& identity) {
+void PerfettoService::BindOnSequence(mojom::PerfettoServiceRequest request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  bindings_.AddBinding(this, std::move(request), identity);
+  bindings_.AddBinding(this, std::move(request));
 }
 
 void PerfettoService::ConnectToProducerHost(
diff --git a/services/tracing/perfetto/perfetto_service.h b/services/tracing/perfetto/perfetto_service.h
index 7be1c65d..1bcb1c8 100644
--- a/services/tracing/perfetto/perfetto_service.h
+++ b/services/tracing/perfetto/perfetto_service.h
@@ -17,10 +17,6 @@
 #include "services/tracing/public/cpp/perfetto/task_runner.h"
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
 
-namespace service_manager {
-struct BindSourceInfo;
-}  // namespace service_manager
-
 namespace perfetto {
 class TracingService;
 }  // namespace perfetto
@@ -39,8 +35,7 @@
 
   static PerfettoService* GetInstance();
 
-  void BindRequest(mojom::PerfettoServiceRequest request,
-                   const service_manager::BindSourceInfo& source_info);
+  void BindRequest(mojom::PerfettoServiceRequest request);
 
   // mojom::PerfettoService implementation.
   void ConnectToProducerHost(mojom::ProducerClientPtr producer_client,
@@ -52,13 +47,12 @@
   }
 
  private:
-  void BindOnSequence(mojom::PerfettoServiceRequest request,
-                      const service_manager::Identity& identity);
+  void BindOnSequence(mojom::PerfettoServiceRequest request);
   void CreateServiceOnSequence();
 
   PerfettoTaskRunner perfetto_task_runner_;
   std::unique_ptr<perfetto::TracingService> service_;
-  mojo::BindingSet<mojom::PerfettoService, service_manager::Identity> bindings_;
+  mojo::BindingSet<mojom::PerfettoService> bindings_;
   mojo::StrongBindingSet<mojom::ProducerHost> producer_bindings_;
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
index 109ee11..1916281c 100644
--- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc
+++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -69,8 +69,11 @@
 };
 
 PerfettoTracingCoordinator::PerfettoTracingCoordinator(
-    AgentRegistry* agent_registry)
-    : Coordinator(agent_registry), binding_(this), weak_factory_(this) {
+    AgentRegistry* agent_registry,
+    base::RepeatingClosure on_disconnect_callback)
+    : Coordinator(agent_registry, std::move(on_disconnect_callback)),
+      binding_(this),
+      weak_factory_(this) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
@@ -81,6 +84,8 @@
 void PerfettoTracingCoordinator::OnClientConnectionError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   tracing_session_.reset();
+  binding_.Close();
+  Coordinator::OnClientConnectionError();
 }
 
 void PerfettoTracingCoordinator::BindCoordinatorRequest(
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.h b/services/tracing/perfetto/perfetto_tracing_coordinator.h
index add85bb..26b53ed 100644
--- a/services/tracing/perfetto/perfetto_tracing_coordinator.h
+++ b/services/tracing/perfetto/perfetto_tracing_coordinator.h
@@ -26,7 +26,8 @@
 // collecting trace events behind the scenes.
 class PerfettoTracingCoordinator : public Coordinator {
  public:
-  explicit PerfettoTracingCoordinator(AgentRegistry* agent_registry);
+  PerfettoTracingCoordinator(AgentRegistry* agent_registry,
+                             base::RepeatingClosure on_disconnect_callback);
 
   ~PerfettoTracingCoordinator() override;
 
@@ -48,7 +49,7 @@
  private:
   void BindOnSequence(mojom::CoordinatorRequest request);
   void OnTracingOverCallback();
-  void OnClientConnectionError();
+  void OnClientConnectionError() override;
 
   mojo::Binding<mojom::Coordinator> binding_;
 
diff --git a/services/tracing/public/DEPS b/services/tracing/public/DEPS
new file mode 100644
index 0000000..938b520
--- /dev/null
+++ b/services/tracing/public/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "-services/service_manager/public",  # The service_manager client lib depends on the tracing one
+]
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn
index dfd910a..78417c7 100644
--- a/services/tracing/public/cpp/BUILD.gn
+++ b/services/tracing/public/cpp/BUILD.gn
@@ -18,6 +18,8 @@
     "perfetto/traced_value_proto_writer.h",
     "trace_event_agent.cc",
     "trace_event_agent.h",
+    "traced_process.cc",
+    "traced_process.h",
     "tracing_features.cc",
     "tracing_features.h",
   ]
@@ -30,7 +32,6 @@
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/service_manager/public/cpp",
     "//services/tracing/public/mojom",
     "//third_party/perfetto:libperfetto",
   ]
diff --git a/services/tracing/public/cpp/base_agent.cc b/services/tracing/public/cpp/base_agent.cc
index 1575036..f15a8d9b 100644
--- a/services/tracing/public/cpp/base_agent.cc
+++ b/services/tracing/public/cpp/base_agent.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "services/service_manager/public/cpp/connector.h"
+#include "services/tracing/public/cpp/traced_process.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 
 namespace tracing {
@@ -14,22 +14,29 @@
 BaseAgent::BaseAgent(const std::string& label,
                      mojom::TraceDataType type,
                      base::ProcessId pid)
-    : binding_(this), label_(label), type_(type), pid_(pid) {}
+    : binding_(this), label_(label), type_(type), pid_(pid) {
+  TracedProcess::GetInstance()->RegisterAgent(this);
+}
 
-BaseAgent::~BaseAgent() = default;
+BaseAgent::~BaseAgent() {
+  TracedProcess::GetInstance()->UnregisterAgent(this);
+}
 
-void BaseAgent::Connect(service_manager::Connector* connector) {
-  DCHECK(!binding_ || !binding_.is_bound());
-  tracing::mojom::AgentRegistryPtr agent_registry;
-  connector->BindInterface(tracing::mojom::kServiceName, &agent_registry);
-
+void BaseAgent::Connect(tracing::mojom::AgentRegistry* agent_registry) {
   tracing::mojom::AgentPtr agent;
   binding_.Bind(mojo::MakeRequest(&agent));
+  binding_.set_connection_error_handler(
+      base::BindRepeating(&BaseAgent::Disconnect, base::Unretained(this)));
+
   agent_registry->RegisterAgent(std::move(agent), label_, type_, pid_);
 }
 
 void BaseAgent::GetCategories(std::set<std::string>* category_set) {}
 
+void BaseAgent::Disconnect() {
+  binding_.Close();
+}
+
 void BaseAgent::StartTracing(const std::string& config,
                              base::TimeTicks coordinator_time,
                              Agent::StartTracingCallback callback) {
diff --git a/services/tracing/public/cpp/base_agent.h b/services/tracing/public/cpp/base_agent.h
index f93c8dc..8be2cf54 100644
--- a/services/tracing/public/cpp/base_agent.h
+++ b/services/tracing/public/cpp/base_agent.h
@@ -5,16 +5,13 @@
 #ifndef SERVICES_TRACING_PUBLIC_CPP_BASE_AGENT_H_
 #define SERVICES_TRACING_PUBLIC_CPP_BASE_AGENT_H_
 
+#include <set>
 #include <string>
 
 #include "base/component_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/tracing/public/mojom/tracing.mojom.h"
 
-namespace service_manager {
-class Connector;
-}  // namespace service_manager
-
 // This class is a minimal implementation of mojom::Agent to reduce boilerplate
 // code in tracing agents. A tracing agent can inherit from this class and only
 // override methods that actually do something, in most cases only StartTracing
@@ -24,7 +21,8 @@
  public:
   ~BaseAgent() override;
 
-  virtual void Connect(service_manager::Connector* connector);
+  void Connect(tracing::mojom::AgentRegistry* agent_registry);
+
   virtual void GetCategories(std::set<std::string>* category_set);
 
  protected:
@@ -33,6 +31,8 @@
             base::ProcessId pid);
 
  private:
+  void Disconnect();
+
   // tracing::mojom::Agent:
   void StartTracing(const std::string& config,
                     base::TimeTicks coordinator_time,
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc
index 4ad615f..00d781c 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -8,7 +8,6 @@
 
 #include "base/no_destructor.h"
 #include "base/task/post_task.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "services/tracing/public/cpp/perfetto/shared_memory.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 #include "third_party/perfetto/include/perfetto/tracing/core/commit_data_request.h"
@@ -81,10 +80,7 @@
   GetPerfettoTaskRunner()->ResetTaskRunnerForTesting(CreateTaskRunner());
 }
 
-void ProducerClient::Connect(service_manager::Connector* connector) {
-  mojom::PerfettoServicePtr perfetto_service;
-  connector->BindInterface(mojom::kServiceName, &perfetto_service);
-
+void ProducerClient::Connect(mojom::PerfettoServicePtr perfetto_service) {
   CreateMojoMessagepipes(base::BindOnce(
       [](mojom::PerfettoServicePtr perfetto_service,
          mojom::ProducerClientPtr producer_client_pipe,
diff --git a/services/tracing/public/cpp/perfetto/producer_client.h b/services/tracing/public/cpp/perfetto/producer_client.h
index 1473236..7514d7c 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/services/tracing/public/cpp/perfetto/producer_client.h
@@ -25,10 +25,6 @@
 class SharedMemoryArbiter;
 }  // namespace perfetto
 
-namespace service_manager {
-class Connector;
-}  // namespace service_manager
-
 namespace tracing {
 
 class MojoSharedMemory;
@@ -84,7 +80,7 @@
   // Returns the taskrunner used by Perfetto.
   static base::SequencedTaskRunner* GetTaskRunner();
 
-  void Connect(service_manager::Connector* connector);
+  void Connect(mojom::PerfettoServicePtr perfetto_service);
 
   // Create the messagepipes that'll be used to connect
   // to the service-side ProducerHost, on the correct
diff --git a/services/tracing/public/cpp/trace_event_agent.cc b/services/tracing/public/cpp/trace_event_agent.cc
index 214b90d..94cc70a 100644
--- a/services/tracing/public/cpp/trace_event_agent.cc
+++ b/services/tracing/public/cpp/trace_event_agent.cc
@@ -48,16 +48,6 @@
 
 TraceEventAgent::~TraceEventAgent() = default;
 
-void TraceEventAgent::Connect(service_manager::Connector* connector) {
-  // |connector| can be null in tests.
-  if (!connector) {
-    return;
-  }
-
-  BaseAgent::Connect(connector);
-  ProducerClient::Get()->Connect(connector);
-}
-
 void TraceEventAgent::GetCategories(std::set<std::string>* category_set) {
   for (size_t i = base::trace_event::BuiltinCategories::kVisibleCategoryStart;
        i < base::trace_event::BuiltinCategories::Size(); ++i) {
diff --git a/services/tracing/public/cpp/trace_event_agent.h b/services/tracing/public/cpp/trace_event_agent.h
index bceea7e..70063d2 100644
--- a/services/tracing/public/cpp/trace_event_agent.h
+++ b/services/tracing/public/cpp/trace_event_agent.h
@@ -6,6 +6,7 @@
 #define SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_AGENT_H_
 
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -21,10 +22,6 @@
 class TimeTicks;
 }  // namespace base
 
-namespace service_manager {
-class Connector;
-}  // namespace service_manager
-
 namespace tracing {
 
 // Agent used to interface with the legacy tracing system.
@@ -36,7 +33,6 @@
  public:
   static TraceEventAgent* GetInstance();
 
-  void Connect(service_manager::Connector* connector) override;
   void GetCategories(std::set<std::string>* category_set) override;
 
   using MetadataGeneratorFunction =
diff --git a/services/tracing/public/cpp/traced_process.cc b/services/tracing/public/cpp/traced_process.cc
new file mode 100644
index 0000000..33117ad9
--- /dev/null
+++ b/services/tracing/public/cpp/traced_process.cc
@@ -0,0 +1,101 @@
+// Copyright 2019 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 "services/tracing/public/cpp/traced_process.h"
+
+#include <utility>
+
+#include "base/no_destructor.h"
+#include "services/tracing/public/cpp/base_agent.h"
+#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
+#include "services/tracing/public/mojom/constants.mojom.h"
+
+namespace tracing {
+
+// static
+TracedProcess* TracedProcess::GetInstance() {
+  static base::NoDestructor<TracedProcess> traced_process;
+  return traced_process.get();
+}
+
+TracedProcess::TracedProcess() : binding_(this) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+TracedProcess::~TracedProcess() = default;
+
+// OnTracedProcessRequest can be called concurrently from
+// multiple threads, as we get one call per service.
+void TracedProcess::OnTracedProcessRequest(
+    mojom::TracedProcessRequest request) {
+  if (task_runner_ && !task_runner_->RunsTasksInCurrentSequence()) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&TracedProcess::OnTracedProcessRequest,
+                                  base::Unretained(this), std::move(request)));
+    return;
+  }
+
+  // We only need one binding per process.
+  base::AutoLock lock(lock_);
+  if (binding_.is_bound()) {
+    return;
+  }
+
+  binding_.Bind(std::move(request));
+}
+
+// SetTaskRunner must be called before we start receiving
+// any OnTracedProcessRequest calls.
+void TracedProcess::SetTaskRunner(
+    scoped_refptr<base::SequencedTaskRunner> task_runner) {
+  DCHECK(!binding_.is_bound());
+  DCHECK(!task_runner_);
+  task_runner_ = task_runner;
+}
+
+void TracedProcess::RegisterAgent(BaseAgent* agent) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (agent_registry_) {
+    agent->Connect(agent_registry_.get());
+  }
+
+  agents_.insert(agent);
+}
+
+void TracedProcess::UnregisterAgent(BaseAgent* agent) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  agents_.erase(agent);
+}
+
+void TracedProcess::ConnectToTracingService(
+    mojom::ConnectToTracingRequestPtr request) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // Ensure the TraceEventAgent has been created.
+  TraceEventAgent::GetInstance();
+
+  agent_registry_ =
+      tracing::mojom::AgentRegistryPtr(std::move(request->agent_registry));
+  agent_registry_.set_connection_error_handler(base::BindRepeating(
+      [](TracedProcess* traced_process) {
+        // If the AgentRegistryPtr connection closes, the tracing service
+        // has gone down and we'll start accepting new connections from it
+        // again.
+        base::AutoLock lock(traced_process->lock_);
+        traced_process->agent_registry_.reset();
+        traced_process->binding_.Close();
+      },
+      base::Unretained(this)));
+
+  for (auto* agent : agents_) {
+    agent->Connect(agent_registry_.get());
+  }
+
+  ProducerClient::Get()->Connect(
+      tracing::mojom::PerfettoServicePtr(std::move(request->perfetto_service)));
+}
+
+}  // namespace tracing
diff --git a/services/tracing/public/cpp/traced_process.h b/services/tracing/public/cpp/traced_process.h
new file mode 100644
index 0000000..c85eb27
--- /dev/null
+++ b/services/tracing/public/cpp/traced_process.h
@@ -0,0 +1,60 @@
+// Copyright 2019 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 SERVICES_TRACING_PUBLIC_CPP_TRACED_PROCESS_H_
+#define SERVICES_TRACING_PUBLIC_CPP_TRACED_PROCESS_H_
+
+#include <set>
+#include <string>
+
+#include "base/component_export.h"
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/tracing/public/mojom/tracing.mojom.h"
+
+namespace tracing {
+
+class BaseAgent;
+
+// Each running process will bind this singleton
+// to the mojom::TracedProcess interface, which will be
+// connected to by the tracing service to enable tracing
+// support.
+class COMPONENT_EXPORT(TRACING_CPP) TracedProcess
+    : public mojom::TracedProcess {
+ public:
+  static TracedProcess* GetInstance();
+
+  void OnTracedProcessRequest(mojom::TracedProcessRequest request);
+
+  // Set which taskrunner to bind any incoming requests on.
+  void SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+  void RegisterAgent(BaseAgent* agent);
+  void UnregisterAgent(BaseAgent* agent);
+
+ private:
+  friend class base::NoDestructor<TracedProcess>;
+  TracedProcess();
+  ~TracedProcess() override;
+
+  // tracing::mojom::TracedProcess:
+  void ConnectToTracingService(
+      mojom::ConnectToTracingRequestPtr request) override;
+
+  // Lock protecting binding_.
+  base::Lock lock_;
+  std::set<BaseAgent*> agents_;
+  tracing::mojom::AgentRegistryPtr agent_registry_;
+  mojo::Binding<tracing::mojom::TracedProcess> binding_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+  DISALLOW_COPY_AND_ASSIGN(TracedProcess);
+};
+
+}  // namespace tracing
+
+#endif  // SERVICES_TRACING_PUBLIC_CPP_TRACED_PROCESS_H_
diff --git a/services/tracing/public/mojom/tracing.mojom b/services/tracing/public/mojom/tracing.mojom
index 69e1df7..99d6cfd 100644
--- a/services/tracing/public/mojom/tracing.mojom
+++ b/services/tracing/public/mojom/tracing.mojom
@@ -7,6 +7,19 @@
 import "mojo/public/mojom/base/process_id.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/values.mojom";
+import "services/tracing/public/mojom/perfetto_service.mojom";
+
+struct ConnectToTracingRequest {
+  PerfettoService perfetto_service;
+  AgentRegistry agent_registry;
+};
+
+// The tracing service will bind this interface on every other service,
+// and pass it pointers to the interfaces within the tracing service
+// that the other services should register themselves with.
+interface TracedProcess {
+  ConnectToTracingService(ConnectToTracingRequest request);
+};
 
 // The JSON type of data coming from a tracing agents.
 //
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc
index 9d1d088..15a97e6f 100644
--- a/services/tracing/tracing_service.cc
+++ b/services/tracing/tracing_service.cc
@@ -5,8 +5,10 @@
 #include "services/tracing/tracing_service.h"
 
 #include <utility>
+#include <vector>
 
 #include "base/timer/timer.h"
+#include "services/service_manager/public/mojom/service_manager.mojom.h"
 #include "services/tracing/agent_registry.h"
 #include "services/tracing/coordinator.h"
 #include "services/tracing/perfetto/perfetto_service.h"
@@ -15,6 +17,75 @@
 
 namespace tracing {
 
+// Listener used to connect to every other service and
+// pass them the needed interface pointers to connect
+// back and register with the tracing service.
+class ServiceListener : public service_manager::mojom::ServiceManagerListener {
+ public:
+  ServiceListener(service_manager::Connector* connector,
+                  scoped_refptr<base::SequencedTaskRunner> task_runner,
+                  AgentRegistry* agent_registry)
+      : binding_(this),
+        connector_(connector),
+        task_runner_(task_runner),
+        agent_registry_(agent_registry) {
+    service_manager::mojom::ServiceManagerPtr service_manager;
+    connector_->BindInterface(service_manager::mojom::kServiceName,
+                              &service_manager);
+    service_manager::mojom::ServiceManagerListenerPtr listener;
+    service_manager::mojom::ServiceManagerListenerRequest request(
+        mojo::MakeRequest(&listener));
+    service_manager->AddListener(std::move(listener));
+    binding_.Bind(std::move(request));
+  }
+
+  void ConnectProcessToTracingService(
+      const service_manager::Identity& identity) {
+    mojom::TracedProcessPtr traced_process;
+    connector_->BindInterface(
+        service_manager::ServiceFilter::ForExactIdentity(identity),
+        &traced_process);
+
+    auto new_connection_request = mojom::ConnectToTracingRequest::New();
+
+    PerfettoService::GetInstance()->BindRequest(
+        mojo::MakeRequest(&new_connection_request->perfetto_service));
+
+    agent_registry_->BindAgentRegistryRequest(
+        task_runner_,
+        mojo::MakeRequest(&new_connection_request->agent_registry));
+
+    traced_process->ConnectToTracingService(std::move(new_connection_request));
+  }
+
+  // service_manager::mojom::ServiceManagerListener implementation.
+  void OnInit(std::vector<service_manager::mojom::RunningServiceInfoPtr>
+                  running_services) override {
+    for (auto& service : running_services) {
+      ConnectProcessToTracingService(service->identity);
+    }
+  }
+
+  void OnServiceStarted(const service_manager::Identity& identity,
+                        uint32_t pid) override {
+    ConnectProcessToTracingService(identity);
+  }
+
+  void OnServiceCreated(
+      service_manager::mojom::RunningServiceInfoPtr service) override {}
+  void OnServicePIDReceived(const service_manager::Identity& identity,
+                            uint32_t pid) override {}
+  void OnServiceFailedToStart(
+      const service_manager::Identity& identity) override {}
+  void OnServiceStopped(const service_manager::Identity& identity) override {}
+
+ private:
+  mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
+  service_manager::Connector* connector_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  AgentRegistry* agent_registry_;
+};
+
 TracingService::TracingService(service_manager::mojom::ServiceRequest request)
     : service_binding_(this, std::move(request)),
       task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
@@ -28,34 +99,39 @@
   }
 }
 
+void TracingService::OnDisconnected() {
+  CloseAgentConnectionsAndTerminate();
+}
+
 void TracingService::OnStart() {
   tracing_agent_registry_ = std::make_unique<AgentRegistry>();
 
-  registry_.AddInterface(base::BindRepeating(
-      &tracing::PerfettoService::BindRequest,
-      base::Unretained(tracing::PerfettoService::GetInstance())));
-
   if (TracingUsesPerfettoBackend()) {
     task_runner_ = tracing::PerfettoService::GetInstance()->task_runner();
 
     auto perfetto_coordinator = std::make_unique<PerfettoTracingCoordinator>(
-        tracing_agent_registry_.get());
+        tracing_agent_registry_.get(),
+        base::BindRepeating(&TracingService::OnCoordinatorConnectionClosed,
+                            base::Unretained(this),
+                            base::SequencedTaskRunnerHandle::Get()));
     registry_.AddInterface(
         base::BindRepeating(&PerfettoTracingCoordinator::BindCoordinatorRequest,
                             base::Unretained(perfetto_coordinator.get())));
     perfetto_tracing_coordinator_ = std::move(perfetto_coordinator);
   } else {
-    auto tracing_coordinator =
-        std::make_unique<Coordinator>(tracing_agent_registry_.get());
+    auto tracing_coordinator = std::make_unique<Coordinator>(
+        tracing_agent_registry_.get(),
+        base::BindRepeating(&TracingService::OnCoordinatorConnectionClosed,
+                            base::Unretained(this), nullptr));
     registry_.AddInterface(
         base::BindRepeating(&Coordinator::BindCoordinatorRequest,
                             base::Unretained(tracing_coordinator.get())));
     tracing_coordinator_ = std::move(tracing_coordinator);
   }
 
-  registry_.AddInterface(base::BindRepeating(
-      &AgentRegistry::BindAgentRegistryRequest,
-      base::Unretained(tracing_agent_registry_.get()), task_runner_));
+  service_listener_ = std::make_unique<ServiceListener>(
+      service_binding_.GetConnector(), task_runner_,
+      tracing_agent_registry_.get());
 }
 
 void TracingService::OnBindInterface(
@@ -66,4 +142,29 @@
                           source_info);
 }
 
+void TracingService::OnCoordinatorConnectionClosed(
+    scoped_refptr<base::SequencedTaskRunner> task_runner) {
+  // TODO(oysteine): Running TracingService and Perfetto on different
+  // sequences is getting messy; refactor so that the service manager
+  // runs the tracing service on a single threaded taskrunner so
+  // Perfetto can use the same.
+  if (task_runner && !task_runner->RunsTasksInCurrentSequence()) {
+    task_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(&TracingService::OnCoordinatorConnectionClosed,
+                       base::Unretained(this), nullptr));
+    return;
+  }
+
+  service_binding_.RequestClose();
+}
+
+void TracingService::CloseAgentConnectionsAndTerminate() {
+  task_runner_->PostTaskAndReply(
+      FROM_HERE,
+      base::BindOnce(&AgentRegistry::DisconnectAllAgents,
+                     base::Unretained(tracing_agent_registry_.get())),
+      base::BindOnce(&TracingService::Terminate, base::Unretained(this)));
+}
+
 }  // namespace tracing
diff --git a/services/tracing/tracing_service.h b/services/tracing/tracing_service.h
index 291c32e..8be2ea7 100644
--- a/services/tracing/tracing_service.h
+++ b/services/tracing/tracing_service.h
@@ -21,6 +21,7 @@
 
 namespace tracing {
 
+class ServiceListener;
 class PerfettoTracingCoordinator;
 
 class TracingService : public service_manager::Service {
@@ -30,11 +31,16 @@
 
   // service_manager::Service:
   void OnStart() override;
+  void OnDisconnected() override;
   void OnBindInterface(const service_manager::BindSourceInfo& source_info,
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override;
 
  private:
+  void OnCoordinatorConnectionClosed(
+      scoped_refptr<base::SequencedTaskRunner> task_runner);
+  void CloseAgentConnectionsAndTerminate();
+
   service_manager::ServiceBinding service_binding_;
 
   service_manager::BinderRegistryWithArgs<
@@ -45,6 +51,8 @@
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::unique_ptr<PerfettoTracingCoordinator> perfetto_tracing_coordinator_;
 
+  std::unique_ptr<ServiceListener> service_listener_;
+
   // WeakPtrFactory members should always come last so WeakPtrs are destructed
   // before other members.
   base::WeakPtrFactory<TracingService> weak_factory_{this};
diff --git a/services/tracing/tracing_service_unittest.cc b/services/tracing/tracing_service_unittest.cc
index e7fcdc4..9738a53 100644
--- a/services/tracing/tracing_service_unittest.cc
+++ b/services/tracing/tracing_service_unittest.cc
@@ -21,7 +21,9 @@
  public:
   TracingServiceTest()
       : service_(
-            test_connector_factory_.RegisterInstance(mojom::kServiceName)) {}
+            test_connector_factory_.RegisterInstance(mojom::kServiceName)) {
+    test_connector_factory_.set_ignore_unknown_service_requests(true);
+  }
   ~TracingServiceTest() override {}
 
  protected:
@@ -38,16 +40,18 @@
 };
 
 TEST_F(TracingServiceTest, TracingServiceInstantiate) {
-  mojom::AgentRegistryPtr agent_registry;
+  mojom::CoordinatorPtr coordinator;
   connector()->BindInterface(mojom::kServiceName,
-                             mojo::MakeRequest(&agent_registry));
+                             mojo::MakeRequest(&coordinator));
 
-  MockAgent agent1;
-  agent_registry->RegisterAgent(agent1.CreateAgentPtr(), "FOO",
-                                mojom::TraceDataType::STRING,
-                                base::kNullProcessId);
-
-  base::RunLoop().RunUntilIdle();
+  base::RunLoop tracing_started;
+  coordinator->IsTracing(base::BindOnce(
+      [](base::OnceClosure callback, bool is_tracing) {
+        EXPECT_FALSE(is_tracing);
+        std::move(callback).Run();
+      },
+      tracing_started.QuitClosure()));
+  tracing_started.Run();
 }
 
 }  // namespace tracing