1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor// Copyright 2013 The Chromium Authors. All rights reserved. 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Use of this source code is governed by a BSD-style license that can be 3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor// found in the LICENSE file. 4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/browser/shell_devtools_frontend.h" 6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/command_line.h" 8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/json/json_reader.h" 9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/path_service.h" 10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/strings/string_number_conversions.h" 11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/strings/stringprintf.h" 12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "base/strings/utf_string_conversions.h" 13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/public/browser/devtools_http_handler.h" 14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/public/browser/render_frame_host.h" 15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/public/browser/render_view_host.h" 16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/public/browser/web_contents.h" 17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/public/common/content_client.h" 18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/browser/shell.h" 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "content/shell/browser/shell_browser_context.h" 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "content/shell/browser/shell_browser_main_parts.h" 21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/browser/shell_content_browser_client.h" 22bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/browser/shell_devtools_delegate.h" 23bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/browser/webkit_test_controller.h" 24bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "content/shell/common/shell_switches.h" 25bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#include "net/base/filename_util.h" 26bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 27bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnornamespace content { 28bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 29bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor// DevTools frontend path for inspector LayoutTests. 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn BringertGURL GetDevToolsPathAsURL(const std::string& settings, 31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor const std::string& frontend_url) { 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!frontend_url.empty()) 33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return GURL(frontend_url); 34bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor base::FilePath dir_exe; 35bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (!PathService::Get(base::DIR_EXE, &dir_exe)) { 36bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor NOTREACHED(); 37bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return GURL(); 38bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#if defined(OS_MACOSX) 40bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // On Mac, the executable is in 41bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // out/Release/Content Shell.app/Contents/MacOS/Content Shell. 42bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // We need to go up 3 directories to get to out/Release. 43bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor dir_exe = dir_exe.AppendASCII("../../.."); 44bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor#endif 45bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor base::FilePath dev_tools_path = dir_exe.AppendASCII( 46bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor "resources/inspector/devtools.html"); 47bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 48bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor GURL result = net::FilePathToFileURL(dev_tools_path); 49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (!settings.empty()) 50 result = GURL(base::StringPrintf("%s?settings=%s&experiments=true", 51 result.spec().c_str(), 52 settings.c_str())); 53 return result; 54} 55 56// static 57ShellDevToolsFrontend* ShellDevToolsFrontend::Show( 58 WebContents* inspected_contents) { 59 return ShellDevToolsFrontend::Show(inspected_contents, "", ""); 60} 61 62// static 63ShellDevToolsFrontend* ShellDevToolsFrontend::Show( 64 WebContents* inspected_contents, 65 const std::string& settings, 66 const std::string& frontend_url) { 67 scoped_refptr<DevToolsAgentHost> agent( 68 DevToolsAgentHost::GetOrCreateFor(inspected_contents)); 69 Shell* shell = Shell::CreateNewWindow(inspected_contents->GetBrowserContext(), 70 GURL(), 71 NULL, 72 MSG_ROUTING_NONE, 73 gfx::Size()); 74 ShellDevToolsFrontend* devtools_frontend = new ShellDevToolsFrontend( 75 shell, 76 agent.get()); 77 78 ShellDevToolsDelegate* delegate = ShellContentBrowserClient::Get()-> 79 shell_browser_main_parts()->devtools_delegate(); 80 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 81 shell->LoadURL(GetDevToolsPathAsURL(settings, frontend_url)); 82 else 83 shell->LoadURL(delegate->devtools_http_handler()->GetFrontendURL()); 84 85 return devtools_frontend; 86} 87 88void ShellDevToolsFrontend::Activate() { 89 frontend_shell_->ActivateContents(web_contents()); 90} 91 92void ShellDevToolsFrontend::Focus() { 93 web_contents()->Focus(); 94} 95 96void ShellDevToolsFrontend::InspectElementAt(int x, int y) { 97 agent_host_->InspectElement(x, y); 98} 99 100void ShellDevToolsFrontend::Close() { 101 frontend_shell_->Close(); 102} 103 104ShellDevToolsFrontend::ShellDevToolsFrontend(Shell* frontend_shell, 105 DevToolsAgentHost* agent_host) 106 : WebContentsObserver(frontend_shell->web_contents()), 107 frontend_shell_(frontend_shell), 108 agent_host_(agent_host) { 109} 110 111ShellDevToolsFrontend::~ShellDevToolsFrontend() { 112} 113 114void ShellDevToolsFrontend::RenderViewCreated( 115 RenderViewHost* render_view_host) { 116 if (!frontend_host_) { 117 frontend_host_.reset(DevToolsFrontendHost::Create(render_view_host, this)); 118 agent_host_->AttachClient(this); 119 } 120} 121 122void ShellDevToolsFrontend::DocumentOnLoadCompletedInMainFrame() { 123 web_contents()->GetMainFrame()->ExecuteJavaScript( 124 base::ASCIIToUTF16("InspectorFrontendAPI.setUseSoftMenu(true);")); 125} 126 127void ShellDevToolsFrontend::WebContentsDestroyed() { 128 agent_host_->DetachClient(); 129 delete this; 130} 131 132void ShellDevToolsFrontend::RenderProcessGone(base::TerminationStatus status) { 133 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 134 WebKitTestController::Get()->DevToolsProcessCrashed(); 135} 136 137void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontend( 138 const std::string& message) { 139 std::string method; 140 std::string browser_message; 141 int id = 0; 142 143 base::ListValue* params = NULL; 144 base::DictionaryValue* dict = NULL; 145 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); 146 if (!parsed_message || 147 !parsed_message->GetAsDictionary(&dict) || 148 !dict->GetString("method", &method) || 149 !dict->GetList("params", ¶ms)) { 150 return; 151 } 152 153 if (method != "sendMessageToBrowser" || 154 params->GetSize() != 1 || 155 !params->GetString(0, &browser_message)) { 156 return; 157 } 158 dict->GetInteger("id", &id); 159 160 agent_host_->DispatchProtocolMessage(browser_message); 161 162 if (id) { 163 std::string code = "InspectorFrontendAPI.embedderMessageAck(" + 164 base::IntToString(id) + ",\"\");"; 165 base::string16 javascript = base::UTF8ToUTF16(code); 166 web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); 167 } 168} 169 170void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( 171 const std::string& message) { 172 agent_host_->DispatchProtocolMessage(message); 173} 174 175void ShellDevToolsFrontend::DispatchProtocolMessage( 176 DevToolsAgentHost* agent_host, const std::string& message) { 177 std::string code = "InspectorFrontendAPI.dispatchMessage(" + message + ");"; 178 base::string16 javascript = base::UTF8ToUTF16(code); 179 web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); 180} 181 182void ShellDevToolsFrontend::AgentHostClosed( 183 DevToolsAgentHost* agent_host, bool replaced) { 184 frontend_shell_->Close(); 185} 186 187} // namespace content 188