blob: d316b2a1c6a1ec8c150ca9e11ad7b2b49e58c319 [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"
[email protected]0e60fce2014-06-04 22:27:2011#include "base/files/file_path.h"
[email protected]90e6c5412013-04-16 22:45:2512#include "base/strings/string_number_conversions.h"
[email protected]8dffd2c2013-12-02 14:14:3813#include "base/strings/stringprintf.h"
[email protected]852b34ba2013-10-03 16:29:0614#include "base/strings/utf_string_conversions.h"
15#include "content/public/browser/devtools_agent_host.h"
[email protected]ee75b8992012-01-27 07:53:5716#include "content/public/browser/devtools_http_handler.h"
[email protected]852b34ba2013-10-03 16:29:0617#include "content/public/browser/devtools_target.h"
18#include "content/public/browser/favicon_status.h"
19#include "content/public/browser/navigation_entry.h"
20#include "content/public/browser/render_view_host.h"
[email protected]eb040992012-10-10 16:56:0021#include "content/public/browser/web_contents.h"
[email protected]90e6c5412013-04-16 22:45:2522#include "content/public/common/content_switches.h"
[email protected]eb040992012-10-10 16:56:0023#include "content/public/common/url_constants.h"
[email protected]efd2c3f2014-03-11 09:57:2524#include "content/public/common/user_agent.h"
[email protected]de7d61ff2013-08-20 11:30:4125#include "content/shell/browser/shell.h"
[email protected]ee75b8992012-01-27 07:53:5726#include "grit/shell_resources.h"
[email protected]1946d9e2013-04-09 01:43:3727#include "net/socket/tcp_listen_socket.h"
[email protected]ee75b8992012-01-27 07:53:5728#include "ui/base/resource/resource_bundle.h"
29
[email protected]ed6635e2012-10-27 00:44:0930#if defined(OS_ANDROID)
31#include "content/public/browser/android/devtools_auth.h"
[email protected]1946d9e2013-04-09 01:43:3732#include "net/socket/unix_domain_socket_posix.h"
[email protected]90e6c5412013-04-16 22:45:2533#endif
[email protected]ed6635e2012-10-27 00:44:0934
[email protected]852b34ba2013-10-03 16:29:0635using content::DevToolsAgentHost;
36using content::RenderViewHost;
37using content::WebContents;
38
[email protected]ed6635e2012-10-27 00:44:0939namespace {
[email protected]90e6c5412013-04-16 22:45:2540
[email protected]8dffd2c2013-12-02 14:14:3841#if defined(OS_ANDROID)
42const char kFrontEndURL[] =
43 "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
44#endif
[email protected]852b34ba2013-10-03 16:29:0645const char kTargetTypePage[] = "page";
46
[email protected]90e6c5412013-04-16 22:45:2547net::StreamListenSocketFactory* CreateSocketFactory() {
48 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
49#if defined(OS_ANDROID)
50 std::string socket_name = "content_shell_devtools_remote";
51 if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
52 socket_name = command_line.GetSwitchValueASCII(
53 switches::kRemoteDebuggingSocketName);
54 }
55 return new net::UnixDomainSocketWithAbstractNamespaceFactory(
[email protected]a0dea2e2013-05-30 12:38:3956 socket_name, "", base::Bind(&content::CanUserConnectToDevTools));
[email protected]90e6c5412013-04-16 22:45:2557#else
58 // See if the user specified a port on the command line (useful for
59 // automation). If not, use an ephemeral port by specifying 0.
60 int port = 0;
61 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
62 int temp_port;
63 std::string port_str =
64 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
65 if (base::StringToInt(port_str, &temp_port) &&
66 temp_port > 0 && temp_port < 65535) {
67 port = temp_port;
68 } else {
69 DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
70 }
71 }
72 return new net::TCPListenSocketFactory("127.0.0.1", port);
[email protected]ed6635e2012-10-27 00:44:0973#endif
[email protected]90e6c5412013-04-16 22:45:2574}
[email protected]852b34ba2013-10-03 16:29:0675
76class Target : public content::DevToolsTarget {
77 public:
78 explicit Target(WebContents* web_contents);
79
80 virtual std::string GetId() const OVERRIDE { return id_; }
[email protected]002195f2014-06-02 07:33:3281 virtual std::string GetParentId() const OVERRIDE { return std::string(); }
[email protected]852b34ba2013-10-03 16:29:0682 virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
83 virtual std::string GetTitle() const OVERRIDE { return title_; }
84 virtual std::string GetDescription() const OVERRIDE { return std::string(); }
[email protected]657d2732014-05-07 10:09:5185 virtual GURL GetURL() const OVERRIDE { return url_; }
86 virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; }
[email protected]852b34ba2013-10-03 16:29:0687 virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
88 return last_activity_time_;
89 }
90 virtual bool IsAttached() const OVERRIDE {
91 return agent_host_->IsAttached();
92 }
93 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
94 return agent_host_;
95 }
96 virtual bool Activate() const OVERRIDE;
97 virtual bool Close() const OVERRIDE;
98
99 private:
100 scoped_refptr<DevToolsAgentHost> agent_host_;
101 std::string id_;
102 std::string title_;
103 GURL url_;
104 GURL favicon_url_;
105 base::TimeTicks last_activity_time_;
106};
107
108Target::Target(WebContents* web_contents) {
109 agent_host_ =
110 DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
111 id_ = agent_host_->GetId();
[email protected]32956122013-12-25 07:29:24112 title_ = base::UTF16ToUTF8(web_contents->GetTitle());
[email protected]852b34ba2013-10-03 16:29:06113 url_ = web_contents->GetURL();
114 content::NavigationController& controller = web_contents->GetController();
115 content::NavigationEntry* entry = controller.GetActiveEntry();
116 if (entry != NULL && entry->GetURL().is_valid())
117 favicon_url_ = entry->GetFavicon().url;
[email protected]9a890452014-02-13 22:21:02118 last_activity_time_ = web_contents->GetLastActiveTime();
[email protected]852b34ba2013-10-03 16:29:06119}
120
121bool Target::Activate() const {
122 RenderViewHost* rvh = agent_host_->GetRenderViewHost();
123 if (!rvh)
124 return false;
125 WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
126 if (!web_contents)
127 return false;
128 web_contents->GetDelegate()->ActivateContents(web_contents);
129 return true;
130}
131
132bool Target::Close() const {
133 RenderViewHost* rvh = agent_host_->GetRenderViewHost();
134 if (!rvh)
135 return false;
136 rvh->ClosePage();
137 return true;
138}
139
[email protected]90e6c5412013-04-16 22:45:25140} // namespace
[email protected]ed6635e2012-10-27 00:44:09141
[email protected]ee75b8992012-01-27 07:53:57142namespace content {
143
[email protected]90e6c5412013-04-16 22:45:25144ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext* browser_context)
[email protected]eb040992012-10-10 16:56:00145 : browser_context_(browser_context) {
[email protected]8dffd2c2013-12-02 14:14:38146 std::string frontend_url;
147#if defined(OS_ANDROID)
[email protected]efd2c3f2014-03-11 09:57:25148 frontend_url = base::StringPrintf(kFrontEndURL, GetWebKitRevision().c_str());
[email protected]8dffd2c2013-12-02 14:14:38149#endif
[email protected]90e6c5412013-04-16 22:45:25150 devtools_http_handler_ =
[email protected]0e60fce2014-06-04 22:27:20151 DevToolsHttpHandler::Start(CreateSocketFactory(), frontend_url, this,
152 base::FilePath());
[email protected]ee75b8992012-01-27 07:53:57153}
154
155ShellDevToolsDelegate::~ShellDevToolsDelegate() {
156}
157
158void ShellDevToolsDelegate::Stop() {
159 // The call below destroys this.
160 devtools_http_handler_->Stop();
161}
162
[email protected]ee75b8992012-01-27 07:53:57163std::string ShellDevToolsDelegate::GetDiscoveryPageHTML() {
[email protected]8dffd2c2013-12-02 14:14:38164#if defined(OS_ANDROID)
165 return std::string();
166#else
[email protected]ee75b8992012-01-27 07:53:57167 return ResourceBundle::GetSharedInstance().GetRawDataResource(
[email protected]4d8bb1a92012-11-01 21:12:40168 IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE).as_string();
[email protected]8dffd2c2013-12-02 14:14:38169#endif
[email protected]ee75b8992012-01-27 07:53:57170}
171
[email protected]ee75b8992012-01-27 07:53:57172bool ShellDevToolsDelegate::BundlesFrontendResources() {
[email protected]8dffd2c2013-12-02 14:14:38173#if defined(OS_ANDROID)
174 return false;
175#else
[email protected]ee75b8992012-01-27 07:53:57176 return true;
[email protected]8dffd2c2013-12-02 14:14:38177#endif
[email protected]ee75b8992012-01-27 07:53:57178}
179
[email protected]d30a36f2013-02-07 04:16:26180base::FilePath ShellDevToolsDelegate::GetDebugFrontendDir() {
181 return base::FilePath();
[email protected]ee75b8992012-01-27 07:53:57182}
183
[email protected]e5ea93b2012-09-27 05:50:36184std::string ShellDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
[email protected]007b3f82013-04-09 08:46:45185 return std::string();
[email protected]e5ea93b2012-09-27 05:50:36186}
187
[email protected]c78ecec212013-10-27 19:34:10188scoped_ptr<DevToolsTarget>
189ShellDevToolsDelegate::CreateNewTarget(const GURL& url) {
[email protected]eb040992012-10-10 16:56:00190 Shell* shell = Shell::CreateNewWindow(browser_context_,
[email protected]c78ecec212013-10-27 19:34:10191 url,
[email protected]eb040992012-10-10 16:56:00192 NULL,
193 MSG_ROUTING_NONE,
[email protected]cdb806722013-01-10 14:18:23194 gfx::Size());
[email protected]852b34ba2013-10-03 16:29:06195 return scoped_ptr<DevToolsTarget>(new Target(shell->web_contents()));
[email protected]eb040992012-10-10 16:56:00196}
197
[email protected]852b34ba2013-10-03 16:29:06198void ShellDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
199 TargetList targets;
200 std::vector<RenderViewHost*> rvh_list =
201 content::DevToolsAgentHost::GetValidRenderViewHosts();
202 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
203 it != rvh_list.end(); ++it) {
204 WebContents* web_contents = WebContents::FromRenderViewHost(*it);
205 if (web_contents)
206 targets.push_back(new Target(web_contents));
207 }
208 callback.Run(targets);
[email protected]2fb8c1d2013-03-11 22:00:17209}
210
[email protected]8b62f8e2013-09-03 19:03:06211scoped_ptr<net::StreamListenSocket>
[email protected]eafc8452013-04-16 04:18:35212ShellDevToolsDelegate::CreateSocketForTethering(
213 net::StreamListenSocket::Delegate* delegate,
214 std::string* name) {
[email protected]8b62f8e2013-09-03 19:03:06215 return scoped_ptr<net::StreamListenSocket>();
[email protected]eafc8452013-04-16 04:18:35216}
217
[email protected]ee75b8992012-01-27 07:53:57218} // namespace content