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.
5 #include "content/shell/browser/shell_devtools_delegate.h"
10 #include "base/command_line.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/browser/devtools_agent_host.h"
14 #include "content/public/browser/devtools_http_handler.h"
15 #include "content/public/browser/devtools_target.h"
16 #include "content/public/browser/favicon_status.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/shell/browser/shell.h"
23 #include "grit/shell_resources.h"
24 #include "net/socket/tcp_listen_socket.h"
25 #include "ui/base/resource/resource_bundle.h"
27 #if defined(OS_ANDROID)
28 #include "content/public/browser/android/devtools_auth.h"
29 #include "net/socket/unix_domain_socket_posix.h"
32 using content::DevToolsAgentHost
;
33 using content::RenderViewHost
;
34 using content::WebContents
;
38 const char kTargetTypePage
[] = "page";
40 net::StreamListenSocketFactory
* CreateSocketFactory() {
41 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
42 #if defined(OS_ANDROID)
43 std::string socket_name
= "content_shell_devtools_remote";
44 if (command_line
.HasSwitch(switches::kRemoteDebuggingSocketName
)) {
45 socket_name
= command_line
.GetSwitchValueASCII(
46 switches::kRemoteDebuggingSocketName
);
48 return new net::UnixDomainSocketWithAbstractNamespaceFactory(
49 socket_name
, "", base::Bind(&content::CanUserConnectToDevTools
));
51 // See if the user specified a port on the command line (useful for
52 // automation). If not, use an ephemeral port by specifying 0.
54 if (command_line
.HasSwitch(switches::kRemoteDebuggingPort
)) {
56 std::string port_str
=
57 command_line
.GetSwitchValueASCII(switches::kRemoteDebuggingPort
);
58 if (base::StringToInt(port_str
, &temp_port
) &&
59 temp_port
> 0 && temp_port
< 65535) {
62 DLOG(WARNING
) << "Invalid http debugger port number " << temp_port
;
65 return new net::TCPListenSocketFactory("127.0.0.1", port
);
69 class Target
: public content::DevToolsTarget
{
71 explicit Target(WebContents
* web_contents
);
73 virtual std::string
GetId() const OVERRIDE
{ return id_
; }
74 virtual std::string
GetType() const OVERRIDE
{ return kTargetTypePage
; }
75 virtual std::string
GetTitle() const OVERRIDE
{ return title_
; }
76 virtual std::string
GetDescription() const OVERRIDE
{ return std::string(); }
77 virtual GURL
GetUrl() const OVERRIDE
{ return url_
; }
78 virtual GURL
GetFaviconUrl() const OVERRIDE
{ return favicon_url_
; }
79 virtual base::TimeTicks
GetLastActivityTime() const OVERRIDE
{
80 return last_activity_time_
;
82 virtual bool IsAttached() const OVERRIDE
{
83 return agent_host_
->IsAttached();
85 virtual scoped_refptr
<DevToolsAgentHost
> GetAgentHost() const OVERRIDE
{
88 virtual bool Activate() const OVERRIDE
;
89 virtual bool Close() const OVERRIDE
;
92 scoped_refptr
<DevToolsAgentHost
> agent_host_
;
97 base::TimeTicks last_activity_time_
;
100 Target::Target(WebContents
* web_contents
) {
102 DevToolsAgentHost::GetOrCreateFor(web_contents
->GetRenderViewHost());
103 id_
= agent_host_
->GetId();
104 title_
= UTF16ToUTF8(web_contents
->GetTitle());
105 url_
= web_contents
->GetURL();
106 content::NavigationController
& controller
= web_contents
->GetController();
107 content::NavigationEntry
* entry
= controller
.GetActiveEntry();
108 if (entry
!= NULL
&& entry
->GetURL().is_valid())
109 favicon_url_
= entry
->GetFavicon().url
;
110 last_activity_time_
= web_contents
->GetLastSelectedTime();
113 bool Target::Activate() const {
114 RenderViewHost
* rvh
= agent_host_
->GetRenderViewHost();
117 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
120 web_contents
->GetDelegate()->ActivateContents(web_contents
);
124 bool Target::Close() const {
125 RenderViewHost
* rvh
= agent_host_
->GetRenderViewHost();
136 ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext
* browser_context
)
137 : browser_context_(browser_context
) {
138 // Note that Content Shell always used bundled DevTools frontend,
139 // even on Android, because the shell is used for running layout tests.
140 devtools_http_handler_
=
141 DevToolsHttpHandler::Start(CreateSocketFactory(), std::string(), this);
144 ShellDevToolsDelegate::~ShellDevToolsDelegate() {
147 void ShellDevToolsDelegate::Stop() {
148 // The call below destroys this.
149 devtools_http_handler_
->Stop();
152 std::string
ShellDevToolsDelegate::GetDiscoveryPageHTML() {
153 return ResourceBundle::GetSharedInstance().GetRawDataResource(
154 IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE
).as_string();
157 bool ShellDevToolsDelegate::BundlesFrontendResources() {
161 base::FilePath
ShellDevToolsDelegate::GetDebugFrontendDir() {
162 return base::FilePath();
165 std::string
ShellDevToolsDelegate::GetPageThumbnailData(const GURL
& url
) {
166 return std::string();
169 scoped_ptr
<DevToolsTarget
> ShellDevToolsDelegate::CreateNewTarget() {
170 Shell
* shell
= Shell::CreateNewWindow(browser_context_
,
171 GURL(kAboutBlankURL
),
175 return scoped_ptr
<DevToolsTarget
>(new Target(shell
->web_contents()));
178 void ShellDevToolsDelegate::EnumerateTargets(TargetCallback callback
) {
180 std::vector
<RenderViewHost
*> rvh_list
=
181 content::DevToolsAgentHost::GetValidRenderViewHosts();
182 for (std::vector
<RenderViewHost
*>::iterator it
= rvh_list
.begin();
183 it
!= rvh_list
.end(); ++it
) {
184 WebContents
* web_contents
= WebContents::FromRenderViewHost(*it
);
186 targets
.push_back(new Target(web_contents
));
188 callback
.Run(targets
);
191 scoped_ptr
<net::StreamListenSocket
>
192 ShellDevToolsDelegate::CreateSocketForTethering(
193 net::StreamListenSocket::Delegate
* delegate
,
195 return scoped_ptr
<net::StreamListenSocket
>();
198 } // namespace content