[DevTools] Move DevToolsAgent to RenderFrameImpl.

BUG=451004

Review URL: https://codereview.chromium.org/1023783004

Cr-Commit-Position: refs/heads/master@{#322382}
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc
index dca9b863..357a47f 100644
--- a/content/renderer/devtools/devtools_agent.cc
+++ b/content/renderer/devtools/devtools_agent.cc
@@ -8,25 +8,20 @@
 
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
-#include "base/process/process_handle.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "content/common/devtools_messages.h"
 #include "content/common/frame_messages.h"
 #include "content/common/view_messages.h"
-#include "content/renderer/devtools/devtools_agent_filter.h"
 #include "content/renderer/devtools/devtools_client.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_widget.h"
 #include "ipc/ipc_channel.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
-#include "third_party/WebKit/public/web/WebConsoleMessage.h"
 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
-#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebSettings.h"
-#include "third_party/WebKit/public/web/WebView.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 
 #if defined(USE_TCMALLOC)
 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
@@ -35,20 +30,15 @@
 using blink::WebConsoleMessage;
 using blink::WebDevToolsAgent;
 using blink::WebDevToolsAgentClient;
-using blink::WebFrame;
+using blink::WebLocalFrame;
 using blink::WebPoint;
 using blink::WebString;
-using blink::WebCString;
-using blink::WebVector;
-using blink::WebView;
 
 using base::trace_event::TraceLog;
 using base::trace_event::TraceOptions;
 
 namespace content {
 
-base::subtle::AtomicWord DevToolsAgent::event_callback_;
-
 namespace {
 
 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
@@ -75,21 +65,18 @@
 
 } //  namespace
 
-DevToolsAgent::DevToolsAgent(RenderFrame* main_render_frame)
-    : RenderFrameObserver(main_render_frame),
+DevToolsAgent::DevToolsAgent(RenderFrameImpl* frame)
+    : RenderFrameObserver(frame),
       is_attached_(false),
       is_devtools_client_(false),
       paused_in_mouse_move_(false),
-      main_render_frame_(main_render_frame) {
+      frame_(frame) {
   g_agent_for_routing_id.Get()[routing_id()] = this;
-
-  main_render_frame_->GetRenderView()->GetWebView()->setDevToolsAgentClient(
-      this);
+  frame_->GetWebFrame()->setDevToolsAgentClient(this);
 }
 
 DevToolsAgent::~DevToolsAgent() {
   g_agent_for_routing_id.Get().erase(routing_id());
-  resetTraceEventCallback();
 }
 
 // Called on the Renderer thread.
@@ -123,51 +110,25 @@
       this, routing_id(), call_id, message.utf8(), state_cookie.utf8());
 }
 
-long DevToolsAgent::processId() {
-  return base::GetCurrentProcId();
-}
-
-int DevToolsAgent::debuggerId() {
-  return routing_id();
-}
-
 blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
     DevToolsAgent::createClientMessageLoop() {
   return new WebKitClientMessageLoopImpl();
 }
 
 void DevToolsAgent::willEnterDebugLoop() {
-  paused_in_mouse_move_ =
-      GetRenderViewImpl()->SendAckForMouseMoveFromDebugger();
+  if (RenderWidget* widget = frame_->GetRenderWidget())
+    paused_in_mouse_move_ = widget->SendAckForMouseMoveFromDebugger();
 }
 
 void DevToolsAgent::didExitDebugLoop() {
-  if (paused_in_mouse_move_) {
-    GetRenderViewImpl()->IgnoreAckForMouseMoveFromDebugger();
+  if (!paused_in_mouse_move_)
+    return;
+  if (RenderWidget* widget = frame_->GetRenderWidget()) {
+    widget->IgnoreAckForMouseMoveFromDebugger();
     paused_in_mouse_move_ = false;
   }
 }
 
-void DevToolsAgent::resetTraceEventCallback()
-{
-  TraceLog::GetInstance()->SetEventCallbackDisabled();
-  base::subtle::NoBarrier_Store(&event_callback_, 0);
-}
-
-void DevToolsAgent::setTraceEventCallback(const WebString& category_filter,
-                                          TraceEventCallback cb) {
-  TraceLog* trace_log = TraceLog::GetInstance();
-  base::subtle::NoBarrier_Store(&event_callback_,
-                                reinterpret_cast<base::subtle::AtomicWord>(cb));
-  if (!!cb) {
-    trace_log->SetEventCallbackEnabled(
-        base::trace_event::CategoryFilter(category_filter.utf8()),
-        TraceEventCallbackWrapper);
-  } else {
-    trace_log->SetEventCallbackDisabled();
-  }
-}
-
 void DevToolsAgent::enableTracing(const WebString& category_filter) {
   TraceLog* trace_log = TraceLog::GetInstance();
   trace_log->SetEnabled(
@@ -180,28 +141,6 @@
 }
 
 // static
-void DevToolsAgent::TraceEventCallbackWrapper(
-    base::TimeTicks timestamp,
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    unsigned long long id,
-    int num_args,
-    const char* const arg_names[],
-    const unsigned char arg_types[],
-    const unsigned long long arg_values[],
-    unsigned char flags) {
-  TraceEventCallback callback =
-      reinterpret_cast<TraceEventCallback>(
-          base::subtle::NoBarrier_Load(&event_callback_));
-  if (callback) {
-    double timestamp_seconds = (timestamp - base::TimeTicks()).InSecondsF();
-    callback(phase, category_group_enabled, name, id, num_args,
-             arg_names, arg_types, arg_values, flags, timestamp_seconds);
-  }
-}
-
-// static
 DevToolsAgent* DevToolsAgent::FromRoutingId(int routing_id) {
   IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(routing_id);
   if (it != g_agent_for_routing_id.Get().end()) {
@@ -288,12 +227,8 @@
 
 void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level,
                                           const std::string& message) {
-  WebView* web_view = main_render_frame_->GetRenderView()->GetWebView();
-  if (!web_view)
-    return;
-
-  WebFrame* main_frame = web_view->mainFrame();
-  if (!main_frame)
+  WebLocalFrame* web_frame = frame_->GetWebFrame();
+  if (!web_frame)
     return;
 
   WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog;
@@ -311,7 +246,7 @@
       target_level = WebConsoleMessage::LevelError;
       break;
   }
-  main_frame->addMessageToConsole(
+  web_frame->addMessageToConsole(
       WebConsoleMessage(target_level, WebString::fromUTF8(message)));
 }
 
@@ -322,22 +257,17 @@
 }
 
 void DevToolsAgent::OnSetupDevToolsClient() {
-  // We only want to register once per render view.
+  // We only want to register once; and only in main frame.
+  DCHECK(!frame_->GetWebFrame() || !frame_->GetWebFrame()->parent());
   if (is_devtools_client_)
     return;
   is_devtools_client_ = true;
-  new DevToolsClient(main_render_frame_);
+  new DevToolsClient(frame_);
 }
 
 WebDevToolsAgent* DevToolsAgent::GetWebAgent() {
-  WebView* web_view = main_render_frame_->GetRenderView()->GetWebView();
-  if (!web_view)
-    return NULL;
-  return web_view->devToolsAgent();
-}
-
-RenderViewImpl* DevToolsAgent::GetRenderViewImpl() {
-  return static_cast<RenderViewImpl*>(main_render_frame_->GetRenderView());
+  WebLocalFrame* web_frame = frame_->GetWebFrame();
+  return web_frame ? web_frame->devToolsAgent() : nullptr;
 }
 
 bool DevToolsAgent::IsAttached() {
diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h
index e2f9531..9db85c4 100644
--- a/content/renderer/devtools/devtools_agent.h
+++ b/content/renderer/devtools/devtools_agent.h
@@ -7,9 +7,6 @@
 
 #include <string>
 
-#include "base/atomicops.h"
-#include "base/basictypes.h"
-#include "base/time/time.h"
 #include "content/public/common/console_message_level.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "third_party/WebKit/public/web/WebDevToolsAgentClient.h"
@@ -20,16 +17,15 @@
 
 namespace content {
 
-class RenderViewImpl;
+class RenderFrameImpl;
 
-// DevToolsAgent belongs to the inspectable RenderView and provides Glue's
-// agents with the communication capabilities. All messages from/to Glue's
-// agents infrastructure are flowing through this communication agent.
-// There is a corresponding DevToolsClient object on the client side.
+// DevToolsAgent belongs to the inspectable RenderFrameImpl and communicates
+// with WebDevToolsAgent. There is a corresponding DevToolsAgentHost
+// on the browser side.
 class DevToolsAgent : public RenderFrameObserver,
                       public blink::WebDevToolsAgentClient {
  public:
-  explicit DevToolsAgent(RenderFrame* main_render_frame);
+  explicit DevToolsAgent(RenderFrameImpl* frame);
   ~DevToolsAgent() override;
 
   // Returns agent instance for its routing id.
@@ -47,28 +43,18 @@
   bool IsAttached();
 
  private:
-  // RenderView::Observer implementation.
+  // RenderFrameObserver implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  // WebDevToolsAgentClient implementation
+  // WebDevToolsAgentClient implementation.
   void sendProtocolMessage(int call_id,
                            const blink::WebString& response,
                            const blink::WebString& state) override;
-  long processId() override;
-  int debuggerId() override;
   blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
       createClientMessageLoop() override;
   void willEnterDebugLoop() override;
   void didExitDebugLoop() override;
 
-  typedef void (*TraceEventCallback)(
-      char phase, const unsigned char*, const char* name, unsigned long long id,
-      int numArgs, const char* const* argNames, const unsigned char* argTypes,
-      const unsigned long long* argValues,
-      unsigned char flags, double timestamp);
-  void resetTraceEventCallback() override;
-  void setTraceEventCallback(const blink::WebString& category_filter,
-                             TraceEventCallback cb) override;
   void enableTracing(const blink::WebString& category_filter) override;
   void disableTracing() override;
 
@@ -83,26 +69,10 @@
   void ContinueProgram();
   void OnSetupDevToolsClient();
 
-  RenderViewImpl* GetRenderViewImpl();
-
-  static void TraceEventCallbackWrapper(
-      base::TimeTicks timestamp,
-      char phase,
-      const unsigned char* category_group_enabled,
-      const char* name,
-      unsigned long long id,
-      int num_args,
-      const char* const arg_names[],
-      const unsigned char arg_types[],
-      const unsigned long long arg_values[],
-      unsigned char flags);
-
   bool is_attached_;
   bool is_devtools_client_;
   bool paused_in_mouse_move_;
-  RenderFrame* main_render_frame_;
-
-  static base::subtle::AtomicWord /* TraceEventCallback */ event_callback_;
+  RenderFrameImpl* frame_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsAgent);
 };
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d640f9d..e5dced9b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -647,6 +647,7 @@
 // RenderFrameImpl ----------------------------------------------------------
 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
     : frame_(NULL),
+      is_local_root_(false),
       render_view_(render_view->AsWeakPtr()),
       routing_id_(routing_id),
       is_swapped_out_(false),
@@ -673,6 +674,7 @@
 #if defined(VIDEO_HOLE)
       contains_media_player_(false),
 #endif
+      devtools_agent_(nullptr),
       geolocation_dispatcher_(NULL),
       push_messaging_dispatcher_(NULL),
       presentation_dispatcher_(NULL),
@@ -730,6 +732,8 @@
 }
 
 void RenderFrameImpl::Initialize() {
+  is_local_root_ = !frame_->parent() || frame_->parent()->isWebRemoteFrame();
+
 #if defined(ENABLE_PLUGINS)
   new PepperBrowserConnection(this);
 #endif
@@ -738,6 +742,12 @@
   if (!frame_->parent())
     new ImageLoadingHelper(this);
 
+  if (is_local_root_ && !render_frame_proxy_) {
+    // DevToolsAgent is a RenderFrameObserver, and will destruct itself
+    // when |this| is deleted.
+    devtools_agent_ = new DevToolsAgent(this);
+  }
+
   // We delay calling this until we have the WebFrame so that any observer or
   // embedder can call GetWebFrame on any RenderFrame.
   GetContentClient()->renderer()->RenderFrameCreated(this);
@@ -3318,10 +3328,14 @@
     return;
 
   // Do not show error page when DevTools is attached.
-  if (render_view_->devtools_agent_ &&
-      render_view_->devtools_agent_->IsAttached()) {
-    return;
+  RenderFrameImpl* localRoot = this;
+  while (localRoot->frame_ && localRoot->frame_->parent() &&
+      localRoot->frame_->parent()->isWebLocalFrame()) {
+    localRoot = RenderFrameImpl::FromWebFrame(localRoot->frame_->parent());
+    DCHECK(localRoot);
   }
+  if (localRoot->devtools_agent_ && localRoot->devtools_agent_->IsAttached())
+    return;
 
   // Display error page, if appropriate.
   std::string error_domain = "http";
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 4f93aad..0494da6 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -74,6 +74,7 @@
 
 class ChildFrameCompositingHelper;
 class CompositorDependencies;
+class DevToolsAgent;
 class DocumentState;
 class ExternalPopupMenu;
 class GeolocationDispatcher;
@@ -755,6 +756,10 @@
   // case of the main frame, but not subframes).
   blink::WebLocalFrame* frame_;
 
+  // Frame is a local root if it is rendered in a process different than parent
+  // or it is a main frame.
+  bool is_local_root_;
+
   base::WeakPtr<RenderViewImpl> render_view_;
   int routing_id_;
   bool is_swapped_out_;
@@ -867,6 +872,10 @@
   bool contains_media_player_;
 #endif
 
+  // The devtools agent for this frame; only created for main frame and
+  // local roots.
+  DevToolsAgent* devtools_agent_;
+
   // The geolocation dispatcher attached to this frame, lazily initialized.
   GeolocationDispatcher* geolocation_dispatcher_;
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 45caf42..7e31a9f 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -71,7 +71,6 @@
 #include "content/public/renderer/render_view_visitor.h"
 #include "content/renderer/browser_plugin/browser_plugin.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
-#include "content/renderer/devtools/devtools_agent.h"
 #include "content/renderer/disambiguation_popup_helper.h"
 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
 #include "content/renderer/drop_data_builder.h"
@@ -409,6 +408,12 @@
     sizes->push_back(gfx::Size(web_sizes[i]));
 }
 
+static blink::WebDevToolsAgent* GetWebDevToolsAgent(WebView* webview) {
+  if (!webview || !webview->mainFrame()->isWebLocalFrame())
+    return nullptr;
+  return webview->mainFrame()->toWebLocalFrame()->devToolsAgent();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 struct RenderViewImpl::PendingFileChooser {
@@ -630,7 +635,6 @@
 #endif
       has_scrolled_focused_editable_node_into_rect_(false),
       speech_recognition_dispatcher_(NULL),
-      devtools_agent_(NULL),
       mouse_lock_dispatcher_(NULL),
 #if defined(OS_ANDROID)
       expected_content_intent_id_(0),
@@ -768,14 +772,14 @@
   new TextInputClientObserver(this);
 #endif  // defined(OS_MACOSX)
 
-  // The next group of objects all implement RenderViewObserver, so are deleted
-  // along with the RenderView automatically.
-  if (!proxy) {
-    devtools_agent_ = new DevToolsAgent(main_render_frame_.get());
+  // TODO(dgozman): do this not for main frame, but for local frame roots.
+  if (blink::WebDevToolsAgent* devToolsAgent = GetWebDevToolsAgent(webview())) {
     if (RenderWidgetCompositor* rwc = compositor())
-      webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
+      devToolsAgent->setLayerTreeId(rwc->GetLayerTreeId());
   }
 
+  // The next group of objects all implement RenderViewObserver, so are deleted
+  // along with the RenderView automatically.
   mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
 
   history_controller_.reset(new HistoryController(this));
@@ -2014,8 +2018,9 @@
   RenderWidgetCompositor* rwc = compositor();
   if (!rwc)
     return;
-  if (webview() && webview()->devToolsAgent())
-    webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
+  // TODO(dgozman): do this not for main frame, but for local frame roots.
+  if (blink::WebDevToolsAgent* devToolsAgent = GetWebDevToolsAgent(webview()))
+    devToolsAgent->setLayerTreeId(rwc->GetLayerTreeId());
 
   bool use_threaded_event_handling = true;
 #if defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 01f1956..3377f2f 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -119,7 +119,6 @@
 
 namespace content {
 
-class DevToolsAgent;
 class HistoryController;
 class HistoryEntry;
 class MouseLockDispatcher;
@@ -908,8 +907,6 @@
   // initialized.
   SpeechRecognitionDispatcher* speech_recognition_dispatcher_;
 
-  DevToolsAgent* devtools_agent_;
-
   // Mouse Lock dispatcher attached to this view.
   MouseLockDispatcher* mouse_lock_dispatcher_;