blob: b5830971e01f3ff1b63723f236c8cbfac59a8b0a [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]ee75b8992012-01-27 07:53:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de7d61ff2013-08-20 11:30:415#include "content/shell/browser/shell_devtools_delegate.h"
[email protected]ee75b8992012-01-27 07:53:576
[email protected]90e6c5412013-04-16 22:45:257#include <vector>
8
[email protected]ed6635e2012-10-27 00:44:099#include "base/bind.h"
[email protected]90e6c5412013-04-16 22:45:2510#include "base/command_line.h"
11#include "base/strings/string_number_conversions.h"
[email protected]8dffd2c2013-12-02 14:14:3812#include "base/strings/stringprintf.h"
[email protected]852b34ba2013-10-03 16:29:0613#include "base/strings/utf_string_conversions.h"
14#include "content/public/browser/devtools_agent_host.h"
[email protected]ee75b8992012-01-27 07:53:5715#include "content/public/browser/devtools_http_handler.h"
[email protected]852b34ba2013-10-03 16:29:0616#include "content/public/browser/devtools_target.h"
17#include "content/public/browser/favicon_status.h"
18#include "content/public/browser/navigation_entry.h"
19#include "content/public/browser/render_view_host.h"
[email protected]eb040992012-10-10 16:56:0020#include "content/public/browser/web_contents.h"
[email protected]90e6c5412013-04-16 22:45:2521#include "content/public/common/content_switches.h"
[email protected]eb040992012-10-10 16:56:0022#include "content/public/common/url_constants.h"
[email protected]de7d61ff2013-08-20 11:30:4123#include "content/shell/browser/shell.h"
[email protected]ee75b8992012-01-27 07:53:5724#include "grit/shell_resources.h"
[email protected]1946d9e2013-04-09 01:43:3725#include "net/socket/tcp_listen_socket.h"
[email protected]ee75b8992012-01-27 07:53:5726#include "ui/base/resource/resource_bundle.h"
[email protected]8dffd2c2013-12-02 14:14:3827#include "webkit/common/user_agent/user_agent_util.h"
[email protected]ee75b8992012-01-27 07:53:5728
[email protected]ed6635e2012-10-27 00:44:0929#if defined(OS_ANDROID)
30#include "content/public/browser/android/devtools_auth.h"
[email protected]1946d9e2013-04-09 01:43:3731#include "net/socket/unix_domain_socket_posix.h"
[email protected]90e6c5412013-04-16 22:45:2532#endif
[email protected]ed6635e2012-10-27 00:44:0933
[email protected]852b34ba2013-10-03 16:29:0634using content::DevToolsAgentHost;
35using content::RenderViewHost;
36using content::WebContents;
37
[email protected]ed6635e2012-10-27 00:44:0938namespace {
[email protected]90e6c5412013-04-16 22:45:2539
[email protected]8dffd2c2013-12-02 14:14:3840#if defined(OS_ANDROID)
41const char kFrontEndURL[] =
42 "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
43#endif
[email protected]852b34ba2013-10-03 16:29:0644const char kTargetTypePage[] = "page";
45
[email protected]90e6c5412013-04-16 22:45:2546net::StreamListenSocketFactory* CreateSocketFactory() {
47 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
48#if defined(OS_ANDROID)
49 std::string socket_name = "content_shell_devtools_remote";
50 if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
51 socket_name = command_line.GetSwitchValueASCII(
52 switches::kRemoteDebuggingSocketName);
53 }
54 return new net::UnixDomainSocketWithAbstractNamespaceFactory(
[email protected]a0dea2e2013-05-30 12:38:3955 socket_name, "", base::Bind(&content::CanUserConnectToDevTools));
[email protected]90e6c5412013-04-16 22:45:2556#else
57 // See if the user specified a port on the command line (useful for
58 // automation). If not, use an ephemeral port by specifying 0.
59 int port = 0;
60 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
61 int temp_port;
62 std::string port_str =
63 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
64 if (base::StringToInt(port_str, &temp_port) &&
65 temp_port > 0 && temp_port < 65535) {
66 port = temp_port;
67 } else {
68 DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
69 }
70 }
71 return new net::TCPListenSocketFactory("127.0.0.1", port);
[email protected]ed6635e2012-10-27 00:44:0972#endif
[email protected]90e6c5412013-04-16 22:45:2573}
[email protected]852b34ba2013-10-03 16:29:0674
75class Target : public content::DevToolsTarget {
76 public:
77 explicit Target(WebContents* web_contents);
78
79 virtual std::string GetId() const OVERRIDE { return id_; }
80 virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
81 virtual std::string GetTitle() const OVERRIDE { return title_; }
82 virtual std::string GetDescription() const OVERRIDE { return std::string(); }
83 virtual GURL GetUrl() const OVERRIDE { return url_; }
84 virtual GURL GetFaviconUrl() const OVERRIDE { return favicon_url_; }
85 virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
86 return last_activity_time_;
87 }
88 virtual bool IsAttached() const OVERRIDE {
89 return agent_host_->IsAttached();
90 }
91 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
92 return agent_host_;
93 }
94 virtual bool Activate() const OVERRIDE;
95 virtual bool Close() const OVERRIDE;
96
97 private:
98 scoped_refptr<DevToolsAgentHost> agent_host_;
99 std::string id_;
100 std::string title_;
101 GURL url_;
102 GURL favicon_url_;
103 base::TimeTicks last_activity_time_;
104};
105
106Target::Target(WebContents* web_contents) {
107 agent_host_ =
108 DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
109 id_ = agent_host_->GetId();
[email protected]32956122013-12-25 07:29:24110 title_ = base::UTF16ToUTF8(web_contents->GetTitle());
[email protected]852b34ba2013-10-03 16:29:06111 url_ = web_contents->GetURL();
112 content::NavigationController& controller = web_contents->GetController();
113 content::NavigationEntry* entry = controller.GetActiveEntry();
114 if (entry != NULL && entry->GetURL().is_valid())
115 favicon_url_ = entry->GetFavicon().url;
116 last_activity_time_ = web_contents->GetLastSelectedTime();
117}
118
119bool Target::Activate() const {
120 RenderViewHost* rvh = agent_host_->GetRenderViewHost();
121 if (!rvh)
122 return false;
123 WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
124 if (!web_contents)
125 return false;
126 web_contents->GetDelegate()->ActivateContents(web_contents);
127 return true;
128}
129
130bool Target::Close() const {
131 RenderViewHost* rvh = agent_host_->GetRenderViewHost();
132 if (!rvh)
133 return false;
134 rvh->ClosePage();
135 return true;
136}
137
[email protected]90e6c5412013-04-16 22:45:25138} // namespace
[email protected]ed6635e2012-10-27 00:44:09139
[email protected]ee75b8992012-01-27 07:53:57140namespace content {
141
[email protected]90e6c5412013-04-16 22:45:25142ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext* browser_context)
[email protected]eb040992012-10-10 16:56:00143 : browser_context_(browser_context) {
[email protected]8dffd2c2013-12-02 14:14:38144 std::string frontend_url;
145#if defined(OS_ANDROID)
146 frontend_url = base::StringPrintf(kFrontEndURL,
147 webkit_glue::GetWebKitRevision().c_str());
148#endif
[email protected]90e6c5412013-04-16 22:45:25149 devtools_http_handler_ =
[email protected]8dffd2c2013-12-02 14:14:38150 DevToolsHttpHandler::Start(CreateSocketFactory(), frontend_url, this);
[email protected]ee75b8992012-01-27 07:53:57151}
152
153ShellDevToolsDelegate::~ShellDevToolsDelegate() {
154}
155
156void ShellDevToolsDelegate::Stop() {
157 // The call below destroys this.
158 devtools_http_handler_->Stop();
159}
160
[email protected]ee75b8992012-01-27 07:53:57161std::string ShellDevToolsDelegate::GetDiscoveryPageHTML() {
[email protected]8dffd2c2013-12-02 14:14:38162#if defined(OS_ANDROID)
163 return std::string();
164#else
[email protected]ee75b8992012-01-27 07:53:57165 return ResourceBundle::GetSharedInstance().GetRawDataResource(
[email protected]4d8bb1a92012-11-01 21:12:40166 IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE).as_string();
[email protected]8dffd2c2013-12-02 14:14:38167#endif
[email protected]ee75b8992012-01-27 07:53:57168}
169
[email protected]ee75b8992012-01-27 07:53:57170bool ShellDevToolsDelegate::BundlesFrontendResources() {
[email protected]8dffd2c2013-12-02 14:14:38171#if defined(OS_ANDROID)
172 return false;
173#else
[email protected]ee75b8992012-01-27 07:53:57174 return true;
[email protected]8dffd2c2013-12-02 14:14:38175#endif
[email protected]ee75b8992012-01-27 07:53:57176}
177
[email protected]d30a36f2013-02-07 04:16:26178base::FilePath ShellDevToolsDelegate::GetDebugFrontendDir() {
179 return base::FilePath();
[email protected]ee75b8992012-01-27 07:53:57180}
181
[email protected]e5ea93b2012-09-27 05:50:36182std::string ShellDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
[email protected]007b3f82013-04-09 08:46:45183 return std::string();
[email protected]e5ea93b2012-09-27 05:50:36184}
185
[email protected]c78ecec212013-10-27 19:34:10186scoped_ptr<DevToolsTarget>
187ShellDevToolsDelegate::CreateNewTarget(const GURL& url) {
[email protected]eb040992012-10-10 16:56:00188 Shell* shell = Shell::CreateNewWindow(browser_context_,
[email protected]c78ecec212013-10-27 19:34:10189 url,
[email protected]eb040992012-10-10 16:56:00190 NULL,
191 MSG_ROUTING_NONE,
[email protected]cdb806722013-01-10 14:18:23192 gfx::Size());
[email protected]852b34ba2013-10-03 16:29:06193 return scoped_ptr<DevToolsTarget>(new Target(shell->web_contents()));
[email protected]eb040992012-10-10 16:56:00194}
195
[email protected]852b34ba2013-10-03 16:29:06196void ShellDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
197 TargetList targets;
198 std::vector<RenderViewHost*> rvh_list =
199 content::DevToolsAgentHost::GetValidRenderViewHosts();
200 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
201 it != rvh_list.end(); ++it) {
202 WebContents* web_contents = WebContents::FromRenderViewHost(*it);
203 if (web_contents)
204 targets.push_back(new Target(web_contents));
205 }
206 callback.Run(targets);
[email protected]2fb8c1d2013-03-11 22:00:17207}
208
[email protected]8b62f8e2013-09-03 19:03:06209scoped_ptr<net::StreamListenSocket>
[email protected]eafc8452013-04-16 04:18:35210ShellDevToolsDelegate::CreateSocketForTethering(
211 net::StreamListenSocket::Delegate* delegate,
212 std::string* name) {
[email protected]8b62f8e2013-09-03 19:03:06213 return scoped_ptr<net::StreamListenSocket>();
[email protected]eafc8452013-04-16 04:18:35214}
215
[email protected]ee75b8992012-01-27 07:53:57216} // namespace content