• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/shell/browser/shell_devtools_frontend.h"
6 
7 #include "base/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/browser/devtools_http_handler.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/content_client.h"
18 #include "content/shell/browser/shell.h"
19 #include "content/shell/browser/shell_browser_context.h"
20 #include "content/shell/browser/shell_browser_main_parts.h"
21 #include "content/shell/browser/shell_content_browser_client.h"
22 #include "content/shell/browser/shell_devtools_delegate.h"
23 #include "content/shell/browser/webkit_test_controller.h"
24 #include "content/shell/common/shell_switches.h"
25 #include "net/base/filename_util.h"
26 
27 namespace content {
28 
29 // DevTools frontend path for inspector LayoutTests.
GetDevToolsPathAsURL(const std::string & settings,const std::string & frontend_url)30 GURL GetDevToolsPathAsURL(const std::string& settings,
31                           const std::string& frontend_url) {
32   if (!frontend_url.empty())
33     return GURL(frontend_url);
34   base::FilePath dir_exe;
35   if (!PathService::Get(base::DIR_EXE, &dir_exe)) {
36     NOTREACHED();
37     return GURL();
38   }
39 #if defined(OS_MACOSX)
40   // On Mac, the executable is in
41   // out/Release/Content Shell.app/Contents/MacOS/Content Shell.
42   // We need to go up 3 directories to get to out/Release.
43   dir_exe = dir_exe.AppendASCII("../../..");
44 #endif
45   base::FilePath dev_tools_path = dir_exe.AppendASCII(
46       "resources/inspector/devtools.html");
47 
48   GURL result = net::FilePathToFileURL(dev_tools_path);
49   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
Show(WebContents * inspected_contents)57 ShellDevToolsFrontend* ShellDevToolsFrontend::Show(
58     WebContents* inspected_contents) {
59   return ShellDevToolsFrontend::Show(inspected_contents, "", "");
60 }
61 
62 // static
Show(WebContents * inspected_contents,const std::string & settings,const std::string & frontend_url)63 ShellDevToolsFrontend* 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 
Activate()88 void ShellDevToolsFrontend::Activate() {
89   frontend_shell_->ActivateContents(web_contents());
90 }
91 
Focus()92 void ShellDevToolsFrontend::Focus() {
93   web_contents()->Focus();
94 }
95 
InspectElementAt(int x,int y)96 void ShellDevToolsFrontend::InspectElementAt(int x, int y) {
97   agent_host_->InspectElement(x, y);
98 }
99 
Close()100 void ShellDevToolsFrontend::Close() {
101   frontend_shell_->Close();
102 }
103 
ShellDevToolsFrontend(Shell * frontend_shell,DevToolsAgentHost * agent_host)104 ShellDevToolsFrontend::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 
~ShellDevToolsFrontend()111 ShellDevToolsFrontend::~ShellDevToolsFrontend() {
112 }
113 
RenderViewCreated(RenderViewHost * render_view_host)114 void 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 
DocumentOnLoadCompletedInMainFrame()122 void ShellDevToolsFrontend::DocumentOnLoadCompletedInMainFrame() {
123   web_contents()->GetMainFrame()->ExecuteJavaScript(
124       base::ASCIIToUTF16("InspectorFrontendAPI.setUseSoftMenu(true);"));
125 }
126 
WebContentsDestroyed()127 void ShellDevToolsFrontend::WebContentsDestroyed() {
128   agent_host_->DetachClient();
129   delete this;
130 }
131 
RenderProcessGone(base::TerminationStatus status)132 void ShellDevToolsFrontend::RenderProcessGone(base::TerminationStatus status) {
133   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
134     WebKitTestController::Get()->DevToolsProcessCrashed();
135 }
136 
HandleMessageFromDevToolsFrontend(const std::string & message)137 void 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", &params)) {
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 
HandleMessageFromDevToolsFrontendToBackend(const std::string & message)170 void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend(
171     const std::string& message) {
172   agent_host_->DispatchProtocolMessage(message);
173 }
174 
DispatchProtocolMessage(DevToolsAgentHost * agent_host,const std::string & message)175 void 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 
AgentHostClosed(DevToolsAgentHost * agent_host,bool replaced)182 void ShellDevToolsFrontend::AgentHostClosed(
183     DevToolsAgentHost* agent_host, bool replaced) {
184   frontend_shell_->Close();
185 }
186 
187 }  // namespace content
188