[DevTools] Plumb mojom::DevToolsAgentHost around

This is a preparation to worker debugging over mojom::DevToolsAgent
interface. To properly report child workers and establish connection
to them, we need a host which will be notified about children.

For now, just plumb an empty interface to separate concerns.
See https://chromium-review.googlesource.com/c/chromium/src/+/1183589
for the full implementation.

Bug: 775132
Change-Id: Iac8b94309cc431baf18871b3355d817b326e51ac
Reviewed-on: https://chromium-review.googlesource.com/c/1265030
Reviewed-by: Andrey Kosyakov <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Commit-Queue: Dmitry Gozman <[email protected]>
Cr-Commit-Position: refs/heads/master@{#598535}
diff --git a/content/browser/devtools/devtools_renderer_channel.cc b/content/browser/devtools/devtools_renderer_channel.cc
index 6a88fb48..bd09fc1 100644
--- a/content/browser/devtools/devtools_renderer_channel.cc
+++ b/content/browser/devtools/devtools_renderer_channel.cc
@@ -13,14 +13,20 @@
 namespace content {
 
 DevToolsRendererChannel::DevToolsRendererChannel(DevToolsAgentHostImpl* owner)
-    : owner_(owner), process_id_(ChildProcessHost::kInvalidUniqueID) {}
+    : owner_(owner),
+      binding_(this),
+      process_id_(ChildProcessHost::kInvalidUniqueID) {}
 
 DevToolsRendererChannel::~DevToolsRendererChannel() = default;
 
 void DevToolsRendererChannel::SetRenderer(
     blink::mojom::DevToolsAgentAssociatedPtr agent_ptr,
+    blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
     int process_id,
     RenderFrameHostImpl* frame_host) {
+  binding_.Close();
+  if (host_request)
+    binding_.Bind(std::move(host_request));
   agent_ptr_ = std::move(agent_ptr);
   process_id_ = process_id;
   frame_host_ = frame_host;
@@ -42,8 +48,8 @@
 void DevToolsRendererChannel::InspectElement(const gfx::Point& point) {
   if (!agent_ptr_)
     owner_->UpdateRendererChannel(true /* force */);
-  // Previous call might update |agent_ptr_| via SetRenderer(),
-  // so we should check it again.
+  // Previous call might update |agent_ptr_|
+  // via SetRenderer(), so we should check it again.
   if (agent_ptr_)
     agent_ptr_->InspectElement(point);
 }
diff --git a/content/browser/devtools/devtools_renderer_channel.h b/content/browser/devtools/devtools_renderer_channel.h
index ecfbf9f7f..1e39045 100644
--- a/content/browser/devtools/devtools_renderer_channel.h
+++ b/content/browser/devtools/devtools_renderer_channel.h
@@ -7,6 +7,8 @@
 
 #include "base/macros.h"
 #include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "third_party/blink/public/web/devtools_agent.mojom.h"
 
 namespace gfx {
@@ -24,19 +26,23 @@
 // When the renderer changes, different DevToolsAgentHostImpl subclasses
 // retrieve a new blink::mojom::DevToolsAgent pointer, and this channel
 // starts using it for all existing and future sessions.
-class CONTENT_EXPORT DevToolsRendererChannel {
+class CONTENT_EXPORT DevToolsRendererChannel
+    : public blink::mojom::DevToolsAgentHost {
  public:
   explicit DevToolsRendererChannel(DevToolsAgentHostImpl* owner);
-  ~DevToolsRendererChannel();
+  ~DevToolsRendererChannel() override;
 
-  void SetRenderer(blink::mojom::DevToolsAgentAssociatedPtr agent_ptr,
-                   int process_id,
-                   RenderFrameHostImpl* frame_host);
+  void SetRenderer(
+      blink::mojom::DevToolsAgentAssociatedPtr agent_ptr,
+      blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
+      int process_id,
+      RenderFrameHostImpl* frame_host);
   void AttachSession(DevToolsSession* session);
   void InspectElement(const gfx::Point& point);
 
  private:
   DevToolsAgentHostImpl* owner_;
+  mojo::AssociatedBinding<blink::mojom::DevToolsAgentHost> binding_;
   blink::mojom::DevToolsAgentAssociatedPtr agent_ptr_;
   int process_id_;
   RenderFrameHostImpl* frame_host_ = nullptr;
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index ff0a598..7c9bfca5 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -921,12 +921,17 @@
 
 void RenderFrameDevToolsAgentHost::UpdateRendererChannel(bool force) {
   blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
-  if (frame_host_ && render_frame_alive_ && force)
-    frame_host_->GetRemoteAssociatedInterfaces()->GetInterface(&agent_ptr);
+  blink::mojom::DevToolsAgentHostAssociatedRequest host_request;
+  if (frame_host_ && render_frame_alive_ && force) {
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+    host_request = mojo::MakeRequest(&host_ptr_info);
+    frame_host_->BindDevToolsAgent(std::move(host_ptr_info),
+                                   mojo::MakeRequest(&agent_ptr));
+  }
   int process_id = frame_host_ ? frame_host_->GetProcess()->GetID()
                                : ChildProcessHost::kInvalidUniqueID;
-  GetRendererChannel()->SetRenderer(std::move(agent_ptr), process_id,
-                                    frame_host_);
+  GetRendererChannel()->SetRenderer(
+      std::move(agent_ptr), std::move(host_request), process_id, frame_host_);
 }
 
 bool RenderFrameDevToolsAgentHost::IsChildFrame() {
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.cc b/content/browser/devtools/service_worker_devtools_agent_host.cc
index 53af8c9..c610a37 100644
--- a/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -136,12 +136,14 @@
 }
 
 void ServiceWorkerDevToolsAgentHost::WorkerReadyForInspection(
+    blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
     blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
   DCHECK_EQ(WORKER_NOT_READY, state_);
   state_ = WORKER_READY;
   blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
   agent_ptr.Bind(std::move(devtools_agent_ptr_info));
-  GetRendererChannel()->SetRenderer(std::move(agent_ptr), worker_process_id_,
+  GetRendererChannel()->SetRenderer(std::move(agent_ptr),
+                                    std::move(host_request), worker_process_id_,
                                     nullptr);
   if (!sessions().empty())
     UpdateIsAttached(true);
@@ -162,8 +164,8 @@
   state_ = WORKER_TERMINATED;
   for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
     inspector->TargetCrashed();
-  GetRendererChannel()->SetRenderer(nullptr, ChildProcessHost::kInvalidUniqueID,
-                                    nullptr);
+  GetRendererChannel()->SetRenderer(
+      nullptr, nullptr, ChildProcessHost::kInvalidUniqueID, nullptr);
   if (!sessions().empty())
     UpdateIsAttached(false);
 }
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.h b/content/browser/devtools/service_worker_devtools_agent_host.h
index 50e66dd7..0b0d0a2 100644
--- a/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -48,6 +48,7 @@
 
   void WorkerRestarted(int worker_process_id, int worker_route_id);
   void WorkerReadyForInspection(
+      blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
       blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info);
   void WorkerDestroyed();
   void WorkerVersionInstalled();
diff --git a/content/browser/devtools/service_worker_devtools_manager.cc b/content/browser/devtools/service_worker_devtools_manager.cc
index e97cdcc..a91474c6 100644
--- a/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/content/browser/devtools/service_worker_devtools_manager.cc
@@ -91,6 +91,7 @@
 void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
     int worker_process_id,
     int worker_route_id,
+    blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
     blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   const WorkerId worker_id(worker_process_id, worker_route_id);
@@ -98,7 +99,8 @@
   if (it == live_hosts_.end())
     return;
   scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
-  host->WorkerReadyForInspection(std::move(devtools_agent_ptr_info));
+  host->WorkerReadyForInspection(std::move(host_request),
+                                 std::move(devtools_agent_ptr_info));
   // Bring up UI for the ones not picked by other clients.
   if (debug_service_worker_on_start_ && !host->IsAttached())
     host->Inspect();
diff --git a/content/browser/devtools/service_worker_devtools_manager.h b/content/browser/devtools/service_worker_devtools_manager.h
index 0153f48..6745d91 100644
--- a/content/browser/devtools/service_worker_devtools_manager.h
+++ b/content/browser/devtools/service_worker_devtools_manager.h
@@ -71,6 +71,7 @@
   void WorkerReadyForInspection(
       int worker_process_id,
       int worker_route_id,
+      blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
       blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info);
   void WorkerVersionInstalled(int worker_process_id, int worker_route_id);
   void WorkerVersionDoomed(int worker_process_id, int worker_route_id);
diff --git a/content/browser/devtools/shared_worker_devtools_agent_host.cc b/content/browser/devtools/shared_worker_devtools_agent_host.cc
index 6a3afed..9d4dd11 100644
--- a/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -115,13 +115,18 @@
 
 void SharedWorkerDevToolsAgentHost::UpdateRendererChannel(bool force) {
   if (state_ == WORKER_READY && force) {
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+    blink::mojom::DevToolsAgentHostAssociatedRequest host_request =
+        mojo::MakeRequest(&host_ptr_info);
     blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
-    worker_host_->BindDevToolsAgent(mojo::MakeRequest(&agent_ptr));
+    worker_host_->BindDevToolsAgent(std::move(host_ptr_info),
+                                    mojo::MakeRequest(&agent_ptr));
     GetRendererChannel()->SetRenderer(std::move(agent_ptr),
+                                      std::move(host_request),
                                       worker_host_->process_id(), nullptr);
   } else {
     GetRendererChannel()->SetRenderer(
-        nullptr, ChildProcessHost::kInvalidUniqueID, nullptr);
+        nullptr, nullptr, ChildProcessHost::kInvalidUniqueID, nullptr);
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index b71ff538..15908f7f 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4717,6 +4717,13 @@
   }
 }
 
+void RenderFrameHostImpl::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+    blink::mojom::DevToolsAgentAssociatedRequest request) {
+  GetNavigationControl()->BindDevToolsAgent(std::move(host),
+                                            std::move(request));
+}
+
 bool RenderFrameHostImpl::IsSameSiteInstance(
     RenderFrameHostImpl* other_render_frame_host) {
   // As a sanity check, make sure the frame belongs to the same BrowserContext.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index b75cf70..a8ef548 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -77,6 +77,7 @@
 #include "third_party/blink/public/platform/web_scroll_types.h"
 #include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
 #include "third_party/blink/public/web/commit_result.mojom.h"
+#include "third_party/blink/public/web/devtools_agent.mojom.h"
 #include "third_party/blink/public/web/web_text_direction.h"
 #include "third_party/blink/public/web/web_tree_scope_type.h"
 #include "ui/accessibility/ax_mode.h"
@@ -718,6 +719,10 @@
   // Cancels any blocked request for the frame and its subframes.
   void CancelBlockedRequestsForFrame();
 
+  // Binds a DevToolsAgent interface for debugging.
+  void BindDevToolsAgent(blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+                         blink::mojom::DevToolsAgentAssociatedRequest request);
+
 #if defined(OS_ANDROID)
   base::android::ScopedJavaLocalRef<jobject> GetJavaRenderFrameHost();
   service_manager::InterfaceProvider* GetJavaInterfaces() override;
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index c99cb14..4c5f7c7 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -56,10 +56,12 @@
 void NotifyWorkerReadyForInspectionOnUI(
     int worker_process_id,
     int worker_route_id,
+    blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
     blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ServiceWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
-      worker_process_id, worker_route_id, std::move(devtools_agent_ptr_info));
+      worker_process_id, worker_route_id, std::move(host_request),
+      std::move(devtools_agent_ptr_info));
 }
 
 void NotifyWorkerDestroyedOnUI(int worker_process_id, int worker_route_id) {
@@ -315,12 +317,14 @@
   }
 
   void NotifyWorkerReadyForInspection(
+      blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
       blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(NotifyWorkerReadyForInspectionOnUI, process_id_,
-                       agent_route_id_, std::move(devtools_agent_ptr_info)));
+                       agent_route_id_, std::move(host_request),
+                       std::move(devtools_agent_ptr_info)));
   }
 
   void NotifyWorkerVersionInstalled() {
@@ -806,12 +810,16 @@
 }
 
 void EmbeddedWorkerInstance::OnReadyForInspection() {
-  if (devtools_proxy_) {
-    blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info;
-    client_->BindDevToolsAgent(mojo::MakeRequest(&devtools_agent_ptr_info));
-    devtools_proxy_->NotifyWorkerReadyForInspection(
-        std::move(devtools_agent_ptr_info));
-  }
+  if (!devtools_proxy_)
+    return;
+  blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+  blink::mojom::DevToolsAgentHostAssociatedRequest host_request =
+      mojo::MakeRequest(&host_ptr_info);
+  blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info;
+  client_->BindDevToolsAgent(std::move(host_ptr_info),
+                             mojo::MakeRequest(&devtools_agent_ptr_info));
+  devtools_proxy_->NotifyWorkerReadyForInspection(
+      std::move(host_request), std::move(devtools_agent_ptr_info));
 }
 
 void EmbeddedWorkerInstance::OnScriptReadStarted() {
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index 13f5947..e3c8fc90 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -83,7 +83,8 @@
     void AddMessageToConsole(blink::WebConsoleMessage::Level level,
                              const std::string& message) override;
     void BindDevToolsAgent(
-        blink::mojom::DevToolsAgentAssociatedRequest request) override {}
+        blink::mojom::DevToolsAgentHostAssociatedPtrInfo,
+        blink::mojom::DevToolsAgentAssociatedRequest) override {}
 
     base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
     mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
diff --git a/content/browser/shared_worker/mock_shared_worker.cc b/content/browser/shared_worker/mock_shared_worker.cc
index 1936d7c..d6b17d1a 100644
--- a/content/browser/shared_worker/mock_shared_worker.cc
+++ b/content/browser/shared_worker/mock_shared_worker.cc
@@ -61,6 +61,7 @@
 }
 
 void MockSharedWorker::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
     blink::mojom::DevToolsAgentAssociatedRequest request) {
   NOTREACHED();
 }
diff --git a/content/browser/shared_worker/mock_shared_worker.h b/content/browser/shared_worker/mock_shared_worker.h
index d9f6f78..7297a82f 100644
--- a/content/browser/shared_worker/mock_shared_worker.h
+++ b/content/browser/shared_worker/mock_shared_worker.h
@@ -40,6 +40,7 @@
                mojo::ScopedMessagePipeHandle port) override;
   void Terminate() override;
   void BindDevToolsAgent(
+      blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
       blink::mojom::DevToolsAgentAssociatedRequest request) override;
 
   mojo::Binding<mojom::SharedWorker> binding_;
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc
index 7715dd77..03f1798 100644
--- a/content/browser/shared_worker/shared_worker_host.cc
+++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -505,8 +505,9 @@
 }
 
 void SharedWorkerHost::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
     blink::mojom::DevToolsAgentAssociatedRequest request) {
-  worker_->BindDevToolsAgent(std::move(request));
+  worker_->BindDevToolsAgent(std::move(host), std::move(request));
 }
 
 void SharedWorkerHost::SetAppCacheHandle(
diff --git a/content/browser/shared_worker/shared_worker_host.h b/content/browser/shared_worker/shared_worker_host.h
index de2700d..0bf7bba 100644
--- a/content/browser/shared_worker/shared_worker_host.h
+++ b/content/browser/shared_worker/shared_worker_host.h
@@ -113,7 +113,8 @@
                  int frame_id,
                  const blink::MessagePortChannel& port);
 
-  void BindDevToolsAgent(blink::mojom::DevToolsAgentAssociatedRequest request);
+  void BindDevToolsAgent(blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+                         blink::mojom::DevToolsAgentAssociatedRequest request);
 
   void SetAppCacheHandle(
       std::unique_ptr<AppCacheNavigationHandle> appcache_handle);
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index f598bf8a2..25346dc 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -23,6 +23,7 @@
 import "third_party/blink/public/mojom/frame/navigation_initiator.mojom";
 import "third_party/blink/public/platform/referrer.mojom";
 import "third_party/blink/public/web/commit_result.mojom";
+import "third_party/blink/public/web/devtools_agent.mojom";
 import "third_party/blink/public/web/window_features.mojom";
 import "ui/base/mojo/window_open_disposition.mojom";
 import "url/mojom/url.mojom";
@@ -151,6 +152,14 @@
   // receiver's existing bundle.
   UpdateSubresourceLoaderFactories(
       URLLoaderFactoryBundle subresource_loader_factories);
+
+  // Returns a DevToolsAgent interface for this frame, used for
+  // remote debugging. See DevToolsAgent for details.
+  // Returned DevToolsAgent must be associated with navigation control,
+  // due to various ordering dependencies between DevTools protocol and
+  // navigation.
+  BindDevToolsAgent(associated blink.mojom.DevToolsAgentHost agent_host,
+                    associated blink.mojom.DevToolsAgent& agent);
 };
 
 // Implemented by the frame (e.g. renderer processes).
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 85dd7db..757640bb 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -110,7 +110,8 @@
   AddMessageToConsole(blink.mojom.ConsoleMessageLevel level, string message);
   // Returns a DevToolsAgent interface for this embedded worker, used for
   // remote debugging. See DevToolsAgent for details.
-  BindDevToolsAgent(associated blink.mojom.DevToolsAgent& devtools_agent);
+  BindDevToolsAgent(associated blink.mojom.DevToolsAgentHost agent_host,
+                    associated blink.mojom.DevToolsAgent& agent);
 };
 
 // EmbeddedWorkerInstanceHost is the browser-side ("Host") of
diff --git a/content/common/shared_worker/shared_worker.mojom b/content/common/shared_worker/shared_worker.mojom
index c7539c4..6a31c53 100644
--- a/content/common/shared_worker/shared_worker.mojom
+++ b/content/common/shared_worker/shared_worker.mojom
@@ -19,5 +19,6 @@
 
   // Binds a DevToolsAgent interface for this shared worker, used for
   // remote debugging. See DevToolsAgent for details.
-  BindDevToolsAgent(associated blink.mojom.DevToolsAgent& devtools_agent);
+  BindDevToolsAgent(associated blink.mojom.DevToolsAgentHost agent_host,
+                    associated blink.mojom.DevToolsAgent& agent);
 };
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index c9b6d0f..1237f83 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3589,6 +3589,12 @@
       ->UpdateThisAndAllClones(std::move(subresource_loaders));
 }
 
+void RenderFrameImpl::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+    blink::mojom::DevToolsAgentAssociatedRequest request) {
+  frame_->BindDevToolsAgent(host.PassHandle(), request.PassHandle());
+}
+
 // mojom::HostZoom implementation ----------------------------------------------
 
 void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index b4fe35c6..ffdb963 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -563,6 +563,9 @@
   void HandleRendererDebugURL(const GURL& url) override;
   void UpdateSubresourceLoaderFactories(
       std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
+  void BindDevToolsAgent(
+      blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+      blink::mojom::DevToolsAgentAssociatedRequest request) override;
 
   // mojom::FullscreenVideoElementHandler implementation:
   void RequestFullscreenVideoElement() override;
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index bdfd146..66b5e22 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -108,9 +108,10 @@
 }
 
 void EmbeddedWorkerInstanceClientImpl::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
     blink::mojom::DevToolsAgentAssociatedRequest request) {
   DCHECK(worker_);
-  worker_->BindDevToolsAgent(request.PassHandle());
+  worker_->BindDevToolsAgent(host.PassHandle(), request.PassHandle());
 }
 
 EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl(
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
index 0448beb..0e4a6072 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.h
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -82,6 +82,7 @@
   void AddMessageToConsole(blink::WebConsoleMessage::Level level,
                            const std::string& message) override;
   void BindDevToolsAgent(
+      blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
       blink::mojom::DevToolsAgentAssociatedRequest request) override;
 
   // Handler of connection error bound to |binding_|.
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 2748b4b..5a15563 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -501,8 +501,9 @@
 }
 
 void EmbeddedSharedWorkerStub::BindDevToolsAgent(
+    blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
     blink::mojom::DevToolsAgentAssociatedRequest request) {
-  impl_->BindDevToolsAgent(request.PassHandle());
+  impl_->BindDevToolsAgent(host.PassHandle(), request.PassHandle());
 }
 
 }  // namespace content
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h
index a9f2386..d75fdd9 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -108,6 +108,7 @@
                mojo::ScopedMessagePipeHandle port) override;
   void Terminate() override;
   void BindDevToolsAgent(
+      blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
       blink::mojom::DevToolsAgentAssociatedRequest request) override;
 
   mojo::Binding<mojom::SharedWorker> binding_;
diff --git a/third_party/blink/public/web/devtools_agent.mojom b/third_party/blink/public/web/devtools_agent.mojom
index 6cf36591..06a578d 100644
--- a/third_party/blink/public/web/devtools_agent.mojom
+++ b/third_party/blink/public/web/devtools_agent.mojom
@@ -76,6 +76,11 @@
   InspectElement(gfx.mojom.Point point);
 };
 
+// This interface is implemented in browser.
+// TODO(dgozman): add methods.
+interface DevToolsAgentHost {
+};
+
 // Represents an attached session which exposes remote debugging protocol.
 // This interface is implemented in renderer hosting entity under debug.
 //
diff --git a/third_party/blink/public/web/web_embedded_worker.h b/third_party/blink/public/web/web_embedded_worker.h
index f71326f..b91eb48 100644
--- a/third_party/blink/public/web/web_embedded_worker.h
+++ b/third_party/blink/public/web/web_embedded_worker.h
@@ -84,6 +84,7 @@
   // Inspector related methods.
   virtual void AddMessageToConsole(const WebConsoleMessage&) = 0;
   virtual void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
       mojo::ScopedInterfaceEndpointHandle devtools_agent_request) = 0;
 };
 
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 543e866..68b3ae21 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -10,6 +10,7 @@
 
 #include "base/callback.h"
 #include "base/unguessable_token.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/frame/sandbox_flags.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
@@ -507,6 +508,12 @@
   virtual WebString Prompt(const WebString& message,
                            const WebString& default_value) = 0;
 
+  // Debugging -----------------------------------------------------------
+
+  virtual void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_request) = 0;
+
   // Editing -------------------------------------------------------------
 
   virtual void SetMarkedText(const WebString& text,
diff --git a/third_party/blink/public/web/web_shared_worker.h b/third_party/blink/public/web/web_shared_worker.h
index 62168f1..1a27776 100644
--- a/third_party/blink/public/web/web_shared_worker.h
+++ b/third_party/blink/public/web/web_shared_worker.h
@@ -87,6 +87,7 @@
 
   virtual void PauseWorkerContextOnStart() = 0;
   virtual void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
       mojo::ScopedInterfaceEndpointHandle devtools_agent_request) = 0;
 
   virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 4509fbe..cb7e1317 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -345,14 +345,15 @@
 void WebDevToolsAgentImpl::WillBeDestroyed() {
   DCHECK(web_local_frame_impl_->GetFrame());
   DCHECK(inspected_frames_->Root()->View());
-  agent_->WillBeDestroyed();
+  agent_->Dispose();
   resource_content_loader_->Dispose();
   worker_client_ = nullptr;
 }
 
 void WebDevToolsAgentImpl::BindRequest(
+    mojom::blink::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
     mojom::blink::DevToolsAgentAssociatedRequest request) {
-  agent_->BindRequest(std::move(request));
+  agent_->BindRequest(std::move(host_ptr_info), std::move(request));
 }
 
 void WebDevToolsAgentImpl::DetachSession(InspectorSession* session) {
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
index f9a84dd..a0169d6 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
@@ -34,7 +34,6 @@
 #include <memory>
 
 #include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/public/web/devtools_agent.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/inspector/devtools_agent.h"
 #include "third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h"
@@ -79,7 +78,8 @@
   void UpdateOverlays();
   bool HandleInputEvent(const WebInputEvent&);
   void DispatchBufferedTouchEvents();
-  void BindRequest(mojom::blink::DevToolsAgentAssociatedRequest);
+  void BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo,
+                   mojom::blink::DevToolsAgentAssociatedRequest);
 
   // Instrumentation from web/ layer.
   void DidCommitLoadForLocalFrame(LocalFrame*);
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index 2f92c92..23a80a2 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -383,9 +383,14 @@
 }
 
 void WebSharedWorkerImpl::BindDevToolsAgent(
+    mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
     mojo::ScopedInterfaceEndpointHandle devtools_agent_request) {
-  shadow_page_->BindDevToolsAgent(mojom::blink::DevToolsAgentAssociatedRequest(
-      std::move(devtools_agent_request)));
+  shadow_page_->DevToolsAgent()->BindRequest(
+      mojom::blink::DevToolsAgentHostAssociatedPtrInfo(
+          std::move(devtools_agent_host_ptr_info),
+          mojom::blink::DevToolsAgentHost::Version_),
+      mojom::blink::DevToolsAgentAssociatedRequest(
+          std::move(devtools_agent_request)));
 }
 
 scoped_refptr<base::SingleThreadTaskRunner> WebSharedWorkerImpl::GetTaskRunner(
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
index cee87b6..ac4becf 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -104,6 +104,7 @@
   void TerminateWorkerContext() override;
   void PauseWorkerContextOnStart() override;
   void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
       mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
 
diff --git a/third_party/blink/renderer/core/exported/worker_shadow_page.cc b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
index 5632438..b5af600 100644
--- a/third_party/blink/renderer/core/exported/worker_shadow_page.cc
+++ b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
@@ -133,9 +133,8 @@
   }
 }
 
-void WorkerShadowPage::BindDevToolsAgent(
-    mojom::blink::DevToolsAgentAssociatedRequest request) {
-  main_frame_->DevToolsAgentImpl()->BindRequest(std::move(request));
+WebDevToolsAgentImpl* WorkerShadowPage::DevToolsAgent() {
+  return main_frame_->DevToolsAgentImpl();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/worker_shadow_page.h b/third_party/blink/renderer/core/exported/worker_shadow_page.h
index 43cf850..753396a 100644
--- a/third_party/blink/renderer/core/exported/worker_shadow_page.h
+++ b/third_party/blink/renderer/core/exported/worker_shadow_page.h
@@ -83,7 +83,7 @@
   WebDocumentLoader* DocumentLoader() {
     return main_frame_->GetDocumentLoader();
   }
-  void BindDevToolsAgent(mojom::blink::DevToolsAgentAssociatedRequest);
+  WebDevToolsAgentImpl* DevToolsAgent();
 
   bool WasInitialized() const;
 
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 64b9642..a7c0e79 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1809,12 +1809,6 @@
     frame_->GetDocument()->GetMutableSecurityOrigin()->GrantUniversalAccess();
   }
 
-  if (frame_->IsLocalRoot()) {
-    frame_->GetInterfaceRegistry()->AddAssociatedInterface(
-        WTF::BindRepeating(&WebLocalFrameImpl::BindDevToolsAgentRequest,
-                           WrapWeakPersistent(this)));
-  }
-
   if (!owner) {
     // This trace event is needed to detect the main frame of the
     // renderer in telemetry metrics. See crbug.com/692112#c11.
@@ -2542,11 +2536,25 @@
   dev_tools_agent_ = agent;
 }
 
-void WebLocalFrameImpl::BindDevToolsAgentRequest(
-    mojom::blink::DevToolsAgentAssociatedRequest request) {
+WebDevToolsAgentImpl* WebLocalFrameImpl::DevToolsAgentImpl() {
+  if (!frame_->IsLocalRoot())
+    return nullptr;
   if (!dev_tools_agent_)
     dev_tools_agent_ = WebDevToolsAgentImpl::CreateForFrame(this);
-  dev_tools_agent_->BindRequest(std::move(request));
+  return dev_tools_agent_;
+}
+
+void WebLocalFrameImpl::BindDevToolsAgent(
+    mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
+    mojo::ScopedInterfaceEndpointHandle devtools_agent_request) {
+  WebDevToolsAgentImpl* agent = DevToolsAgentImpl();
+  if (!agent)
+    return;
+  agent->BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo(
+                         std::move(devtools_agent_host_ptr_info),
+                         mojom::blink::DevToolsAgentHost::Version_),
+                     mojom::blink::DevToolsAgentAssociatedRequest(
+                         std::move(devtools_agent_request)));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 6a68eaa..e857ff9 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -165,6 +165,9 @@
   void SetReferrerForRequest(WebURLRequest&, const WebURL& referrer) override;
   WebAssociatedURLLoader* CreateAssociatedURLLoader(
       const WebAssociatedURLLoaderOptions&) override;
+  void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
   void SetMarkedText(const WebString&,
                      unsigned location,
                      unsigned length) override;
@@ -376,9 +379,7 @@
   }
 
   void SetDevToolsAgentImpl(WebDevToolsAgentImpl*);
-  WebDevToolsAgentImpl* DevToolsAgentImpl() const {
-    return dev_tools_agent_.Get();
-  }
+  WebDevToolsAgentImpl* DevToolsAgentImpl();
 
   // When a Find operation ends, we want to set the selection to what was active
   // and set focus to the first focusable node we find (starting with the first
@@ -474,8 +475,6 @@
 
   Node* ContextMenuNodeInner() const;
 
-  void BindDevToolsAgentRequest(mojom::blink::DevToolsAgentAssociatedRequest);
-
   WebLocalFrameClient* client_;
 
   // TODO(dcheng): Inline this field directly rather than going through Member.
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.cc b/third_party/blink/renderer/core/inspector/devtools_agent.cc
index 4400f14..6d31a13 100644
--- a/third_party/blink/renderer/core/inspector/devtools_agent.cc
+++ b/third_party/blink/renderer/core/inspector/devtools_agent.cc
@@ -211,16 +211,21 @@
   visitor->Trace(sessions_);
 }
 
-void DevToolsAgent::WillBeDestroyed() {
+void DevToolsAgent::Dispose() {
   HeapHashSet<Member<Session>> copy(sessions_);
   for (auto& session : copy)
     session->Detach();
-  binding_.Close();
+  CleanupConnection();
 }
 
 void DevToolsAgent::BindRequest(
+    mojom::blink::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
     mojom::blink::DevToolsAgentAssociatedRequest request) {
+  DCHECK(!binding_);
   binding_.Bind(std::move(request));
+  host_ptr_.Bind(std::move(host_ptr_info));
+  host_ptr_.set_connection_error_handler(
+      WTF::Bind(&DevToolsAgent::CleanupConnection, WrapWeakPersistent(this)));
 }
 
 void DevToolsAgent::AttachDevToolsSession(
@@ -243,4 +248,9 @@
     session->inspector_session()->flushProtocolNotifications();
 }
 
+void DevToolsAgent::CleanupConnection() {
+  binding_.Close();
+  host_ptr_.reset();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.h b/third_party/blink/renderer/core/inspector/devtools_agent.h
index 2ce2cf3..3b0d4ec9 100644
--- a/third_party/blink/renderer/core/inspector/devtools_agent.h
+++ b/third_party/blink/renderer/core/inspector/devtools_agent.h
@@ -39,9 +39,10 @@
                 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
   ~DevToolsAgent() override;
 
-  void WillBeDestroyed();
+  void Dispose();
   void FlushProtocolNotifications();
-  void BindRequest(mojom::blink::DevToolsAgentAssociatedRequest);
+  void BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo,
+                   mojom::blink::DevToolsAgentAssociatedRequest);
   virtual void Trace(blink::Visitor*);
 
  private:
@@ -55,8 +56,11 @@
       mojom::blink::DevToolsSessionStatePtr reattach_session_state) override;
   void InspectElement(const WebPoint& point) override;
 
+  void CleanupConnection();
+
   Client* client_;
   mojo::AssociatedBinding<mojom::blink::DevToolsAgent> binding_;
+  mojom::blink::DevToolsAgentHostAssociatedPtr host_ptr_;
   HeapHashSet<Member<Session>> sessions_;
   scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index 0ef21bc..cd9cda5 100644
--- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -270,9 +270,14 @@
 }
 
 void WebEmbeddedWorkerImpl::BindDevToolsAgent(
+    mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
     mojo::ScopedInterfaceEndpointHandle devtools_agent_request) {
-  shadow_page_->BindDevToolsAgent(mojom::blink::DevToolsAgentAssociatedRequest(
-      std::move(devtools_agent_request)));
+  shadow_page_->DevToolsAgent()->BindRequest(
+      mojom::blink::DevToolsAgentHostAssociatedPtrInfo(
+          std::move(devtools_agent_host_ptr_info),
+          mojom::blink::DevToolsAgentHost::Version_),
+      mojom::blink::DevToolsAgentAssociatedRequest(
+          std::move(devtools_agent_request)));
 }
 
 void WebEmbeddedWorkerImpl::PostMessageToPageInspector(int session_id,
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
index fe54598..7c73402 100644
--- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
+++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
@@ -71,6 +71,7 @@
   void ResumeAfterDownload() override;
   void AddMessageToConsole(const WebConsoleMessage&) override;
   void BindDevToolsAgent(
+      mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
       mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
 
   void PostMessageToPageInspector(int session_id, const WTF::String&);