Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / content / browser / devtools / render_view_devtools_agent_host.cc
index 7bee941..86c0867 100644 (file)
@@ -8,6 +8,7 @@
 #include "base/lazy_instance.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_power_handler.h"
 #include "content/browser/devtools/devtools_protocol.h"
 #include "content/browser/devtools/devtools_protocol_constants.h"
 #include "content/browser/devtools/devtools_tracing_handler.h"
@@ -19,6 +20,7 @@
 #include "content/common/devtools_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/devtools_manager_delegate.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_widget_host_iterator.h"
@@ -35,12 +37,14 @@ typedef std::vector<RenderViewDevToolsAgentHost*> Instances;
 namespace {
 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
 
-static RenderViewDevToolsAgentHost* FindAgentHost(RenderViewHost* rvh) {
+//Returns RenderViewDevToolsAgentHost attached to any of RenderViewHost
+//instances associated with |web_contents|
+static RenderViewDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
   if (g_instances == NULL)
     return NULL;
   for (Instances::iterator it = g_instances.Get().begin();
        it != g_instances.Get().end(); ++it) {
-    if (rvh == (*it)->render_view_host())
+    if ((*it)->GetWebContents() == web_contents)
       return *it;
   }
   return NULL;
@@ -48,43 +52,28 @@ static RenderViewDevToolsAgentHost* FindAgentHost(RenderViewHost* rvh) {
 
 }  // namespace
 
-// static
 scoped_refptr<DevToolsAgentHost>
-DevToolsAgentHost::GetOrCreateFor(RenderViewHost* rvh) {
-  RenderViewDevToolsAgentHost* result = FindAgentHost(rvh);
+DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
+  RenderViewDevToolsAgentHost* result = FindAgentHost(web_contents);
   if (!result)
-    result = new RenderViewDevToolsAgentHost(rvh);
+    result = new RenderViewDevToolsAgentHost(web_contents->GetRenderViewHost());
   return result;
 }
 
 // static
-bool DevToolsAgentHost::HasFor(RenderViewHost* rvh) {
-  return FindAgentHost(rvh) != NULL;
+bool DevToolsAgentHost::HasFor(WebContents* web_contents) {
+  return FindAgentHost(web_contents) != NULL;
 }
 
 // static
 bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) {
-  if (g_instances == NULL)
-    return false;
-  DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
-  if (!devtools_manager)
-    return false;
-  RenderViewHostDelegate* delegate =
-      static_cast<WebContentsImpl*>(web_contents);
-  for (Instances::iterator it = g_instances.Get().begin();
-       it != g_instances.Get().end(); ++it) {
-    RenderViewHost* rvh = (*it)->render_view_host_;
-    if (rvh && rvh->GetDelegate() != delegate)
-      continue;
-    if ((*it)->IsAttached())
-      return true;
-  }
-  return false;
+  RenderViewDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
+  return agent_host && agent_host->IsAttached();
 }
 
 //static
-std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
-  std::vector<RenderViewHost*> result;
+std::vector<WebContents*> DevToolsAgentHost::GetInspectableWebContents() {
+  std::set<WebContents*> set;
   scoped_ptr<RenderWidgetHostIterator> widgets(
       RenderWidgetHost::GetRenderWidgetHosts());
   while (RenderWidgetHost* widget = widgets->GetNextHost()) {
@@ -96,13 +85,11 @@ std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
 
     RenderViewHost* rvh = RenderViewHost::From(widget);
     WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
-    // Don't report a RenderViewHost if it is not the current RenderViewHost
-    // for some WebContents.
-    if (!web_contents || rvh != web_contents->GetRenderViewHost())
-      continue;
-
-    result.push_back(rvh);
+    if (web_contents)
+      set.insert(web_contents);
   }
+  std::vector<WebContents*> result(set.size());
+  std::copy(set.begin(), set.end(), result.begin());
   return result;
 }
 
@@ -110,44 +97,63 @@ std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
 void RenderViewDevToolsAgentHost::OnCancelPendingNavigation(
     RenderViewHost* pending,
     RenderViewHost* current) {
-  RenderViewDevToolsAgentHost* agent_host = FindAgentHost(pending);
+  WebContents* web_contents = WebContents::FromRenderViewHost(pending);
+  RenderViewDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
   if (!agent_host)
     return;
   agent_host->DisconnectRenderViewHost();
   agent_host->ConnectRenderViewHost(current);
 }
 
-RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(
-    RenderViewHost* rvh)
+RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(RenderViewHost* rvh)
     : render_view_host_(NULL),
-      overrides_handler_(new RendererOverridesHandler(this)),
-      tracing_handler_(new DevToolsTracingHandler())
- {
+      overrides_handler_(new RendererOverridesHandler()),
+      tracing_handler_(
+          new DevToolsTracingHandler(DevToolsTracingHandler::Renderer)),
+      power_handler_(new DevToolsPowerHandler()),
+      reattaching_(false) {
   SetRenderViewHost(rvh);
   DevToolsProtocol::Notifier notifier(base::Bind(
       &RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend,
       base::Unretained(this)));
   overrides_handler_->SetNotifier(notifier);
   tracing_handler_->SetNotifier(notifier);
+  power_handler_->SetNotifier(notifier);
   g_instances.Get().push_back(this);
   AddRef();  // Balanced in RenderViewHostDestroyed.
 }
 
-RenderViewHost* RenderViewDevToolsAgentHost::GetRenderViewHost() {
-  return render_view_host_;
+WebContents* RenderViewDevToolsAgentHost::GetWebContents() {
+  return web_contents();
 }
 
 void RenderViewDevToolsAgentHost::DispatchOnInspectorBackend(
     const std::string& message) {
   std::string error_message;
+
+  scoped_ptr<base::DictionaryValue> message_dict(
+      DevToolsProtocol::ParseMessage(message, &error_message));
   scoped_refptr<DevToolsProtocol::Command> command =
-      DevToolsProtocol::ParseCommand(message, &error_message);
+      DevToolsProtocol::ParseCommand(message_dict.get(), &error_message);
 
   if (command) {
-    scoped_refptr<DevToolsProtocol::Response> overridden_response =
-        overrides_handler_->HandleCommand(command);
+    scoped_refptr<DevToolsProtocol::Response> overridden_response;
+
+    DevToolsManagerDelegate* delegate =
+        DevToolsManagerImpl::GetInstance()->delegate();
+    if (delegate) {
+      scoped_ptr<base::DictionaryValue> overridden_response_value(
+          delegate->HandleCommand(this, message_dict.get()));
+      if (overridden_response_value)
+        overridden_response = DevToolsProtocol::ParseResponse(
+            overridden_response_value.get());
+    }
+    if (!overridden_response)
+      overridden_response = overrides_handler_->HandleCommand(command);
     if (!overridden_response)
       overridden_response = tracing_handler_->HandleCommand(command);
+    if (!overridden_response)
+      overridden_response = power_handler_->HandleCommand(command);
     if (overridden_response) {
       if (!overridden_response->is_async_promise())
         OnDispatchOnInspectorFrontend(overridden_response->Serialize());
@@ -169,12 +175,17 @@ void RenderViewDevToolsAgentHost::OnClientAttached() {
   if (!render_view_host_)
     return;
 
-  ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies(
-      render_view_host_->GetProcess()->GetID());
+  InnerOnClientAttached();
 
   // TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
-  // ExtensionProcessManager no longer relies on this notification.
-  DevToolsManagerImpl::GetInstance()->NotifyObservers(this, true);
+  // extensions::ProcessManager no longer relies on this notification.
+  if (!reattaching_)
+    DevToolsManagerImpl::GetInstance()->NotifyObservers(this, true);
+}
+
+void RenderViewDevToolsAgentHost::InnerOnClientAttached() {
+  ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies(
+      render_view_host_->GetProcess()->GetID());
 
 #if defined(OS_ANDROID)
   power_save_blocker_.reset(
@@ -194,20 +205,31 @@ void RenderViewDevToolsAgentHost::OnClientDetached() {
   power_save_blocker_.reset();
 #endif
   overrides_handler_->OnClientDetached();
+  tracing_handler_->OnClientDetached();
+  power_handler_->OnClientDetached();
   ClientDetachedFromRenderer();
+
+  // TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
+  // extensions::ProcessManager no longer relies on this notification.
+  if (!reattaching_)
+    DevToolsManagerImpl::GetInstance()->NotifyObservers(this, false);
 }
 
 void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
   if (!render_view_host_)
     return;
 
+  InnerClientDetachedFromRenderer();
+}
+
+void RenderViewDevToolsAgentHost::InnerClientDetachedFromRenderer() {
   bool process_has_agents = false;
   RenderProcessHost* render_process_host = render_view_host_->GetProcess();
   for (Instances::iterator it = g_instances.Get().begin();
        it != g_instances.Get().end(); ++it) {
     if (*it == this || !(*it)->IsAttached())
       continue;
-    RenderViewHost* rvh = (*it)->render_view_host();
+    RenderViewHost* rvh = (*it)->render_view_host_;
     if (rvh && rvh->GetProcess() == render_process_host)
       process_has_agents = true;
   }
@@ -217,10 +239,6 @@ void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
     ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies(
         render_process_host->GetID());
   }
-
-  // TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
-  // ExtensionProcessManager no longer relies on this notification.
-  DevToolsManagerImpl::GetInstance()->NotifyObservers(this, false);
 }
 
 RenderViewDevToolsAgentHost::~RenderViewDevToolsAgentHost() {
@@ -236,12 +254,30 @@ void RenderViewDevToolsAgentHost::AboutToNavigateRenderView(
   if (!render_view_host_)
     return;
 
-  if (render_view_host_ == dest_rvh && static_cast<RenderViewHostImpl*>(
-          render_view_host_)->render_view_termination_status() ==
+  if (render_view_host_ == dest_rvh &&
+          render_view_host_->render_view_termination_status() ==
               base::TERMINATION_STATUS_STILL_RUNNING)
     return;
+  ReattachToRenderViewHost(dest_rvh);
+}
+
+void RenderViewDevToolsAgentHost::RenderViewHostChanged(
+    RenderViewHost* old_host,
+    RenderViewHost* new_host) {
+  if (new_host != render_view_host_) {
+    // AboutToNavigateRenderView was not called for renderer-initiated
+    // navigation.
+    ReattachToRenderViewHost(new_host);
+  }
+}
+
+void
+RenderViewDevToolsAgentHost::ReattachToRenderViewHost(RenderViewHost* rvh) {
+  DCHECK(!reattaching_);
+  reattaching_ = true;
   DisconnectRenderViewHost();
-  ConnectRenderViewHost(dest_rvh);
+  ConnectRenderViewHost(rvh);
+  reattaching_ = false;
 }
 
 void RenderViewDevToolsAgentHost::RenderViewDeleted(RenderViewHost* rvh) {
@@ -261,6 +297,9 @@ void RenderViewDevToolsAgentHost::RenderProcessGone(
     case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
     case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
     case base::TERMINATION_STATUS_PROCESS_CRASHED:
+#if defined(OS_ANDROID)
+    case base::TERMINATION_STATUS_OOM_PROTECTED:
+#endif
       RenderViewCrashed();
       break;
     default:
@@ -268,6 +307,17 @@ void RenderViewDevToolsAgentHost::RenderProcessGone(
   }
 }
 
+bool RenderViewDevToolsAgentHost::OnMessageReceived(
+    const IPC::Message& message,
+    RenderFrameHost* render_frame_host) {
+  return DispatchIPCMessage(message);
+}
+
+bool RenderViewDevToolsAgentHost::OnMessageReceived(
+    const IPC::Message& message) {
+  return DispatchIPCMessage(message);
+}
+
 void RenderViewDevToolsAgentHost::DidAttachInterstitialPage() {
   if (!render_view_host_)
     return;
@@ -292,9 +342,10 @@ void RenderViewDevToolsAgentHost::Observe(int type,
 
 void RenderViewDevToolsAgentHost::SetRenderViewHost(RenderViewHost* rvh) {
   DCHECK(!render_view_host_);
-  render_view_host_ = rvh;
+  render_view_host_ = static_cast<RenderViewHostImpl*>(rvh);
 
   WebContentsObserver::Observe(WebContents::FromRenderViewHost(rvh));
+  overrides_handler_->SetRenderViewHost(render_view_host_);
 
   registrar_.Add(
       this,
@@ -309,6 +360,15 @@ void RenderViewDevToolsAgentHost::ClearRenderViewHost() {
       content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
       content::Source<RenderWidgetHost>(render_view_host_));
   render_view_host_ = NULL;
+  overrides_handler_->ClearRenderViewHost();
+}
+
+void RenderViewDevToolsAgentHost::DisconnectWebContents() {
+  DisconnectRenderViewHost();
+}
+
+void RenderViewDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
+  ConnectRenderViewHost(wc->GetRenderViewHost());
 }
 
 void RenderViewDevToolsAgentHost::ConnectRenderViewHost(RenderViewHost* rvh) {
@@ -330,7 +390,7 @@ void RenderViewDevToolsAgentHost::RenderViewCrashed() {
       DispatchOnInspectorFrontend(this, notification->Serialize());
 }
 
-bool RenderViewDevToolsAgentHost::OnMessageReceived(
+bool RenderViewDevToolsAgentHost::DispatchIPCMessage(
     const IPC::Message& msg) {
   if (!render_view_host_)
     return false;
@@ -341,11 +401,10 @@ bool RenderViewDevToolsAgentHost::OnMessageReceived(
                         OnDispatchOnInspectorFrontend)
     IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
                         OnSaveAgentRuntimeState)
-    IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCache, OnClearBrowserCache)
-    IPC_MESSAGE_HANDLER(DevToolsHostMsg_ClearBrowserCookies,
-                        OnClearBrowserCookies)
     IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
                                 handled = false; OnSwapCompositorFrame(msg))
+    IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SetTouchEventEmulationEnabled,
+                                handled = OnSetTouchEventEmulationEnabled(msg))
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -353,7 +412,22 @@ bool RenderViewDevToolsAgentHost::OnMessageReceived(
 
 void RenderViewDevToolsAgentHost::OnSwapCompositorFrame(
     const IPC::Message& message) {
-  overrides_handler_->OnSwapCompositorFrame(message);
+  ViewHostMsg_SwapCompositorFrame::Param param;
+  if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
+    return;
+  overrides_handler_->OnSwapCompositorFrame(param.b.metadata);
+}
+
+bool RenderViewDevToolsAgentHost::OnSetTouchEventEmulationEnabled(
+    const IPC::Message& message) {
+  return overrides_handler_->OnSetTouchEventEmulationEnabled();
+}
+
+void RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame(
+    const cc::CompositorFrameMetadata& frame_metadata) {
+  if (!render_view_host_)
+    return;
+  overrides_handler_->OnSwapCompositorFrame(frame_metadata);
 }
 
 void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState(
@@ -367,18 +441,15 @@ void RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend(
     const std::string& message) {
   if (!render_view_host_)
     return;
-  DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
-      this, message);
-}
 
-void RenderViewDevToolsAgentHost::OnClearBrowserCache() {
-  if (render_view_host_)
-    GetContentClient()->browser()->ClearCache(render_view_host_);
-}
+  scoped_refptr<DevToolsProtocol::Notification> notification =
+      DevToolsProtocol::ParseNotification(message);
 
-void RenderViewDevToolsAgentHost::OnClearBrowserCookies() {
-  if (render_view_host_)
-    GetContentClient()->browser()->ClearCookies(render_view_host_);
+  if (notification) {
+    tracing_handler_->HandleNotification(notification);
+  }
+  DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
+      this, message);
 }
 
 }  // namespace content