1 // Copyright (c) 2012 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 "xwalk/runtime/browser/devtools/xwalk_devtools_delegate.h"
9 #include "base/base64.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.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/render_widget_host_view.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/url_constants.h"
22 #include "grit/xwalk_resources.h"
23 #include "net/socket/tcp_listen_socket.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/snapshot/snapshot.h"
26 #include "xwalk/runtime/browser/runtime.h"
28 using content::DevToolsAgentHost;
29 using content::RenderViewHost;
30 using content::RenderWidgetHostView;
31 using content::WebContents;
35 const char kTargetTypePage[] = "page";
36 const char kTargetTypeServiceWorker[] = "service_worker";
37 const char kTargetTypeOther[] = "other";
39 class Target : public content::DevToolsTarget {
41 explicit Target(scoped_refptr<content::DevToolsAgentHost> agent_host);
43 virtual std::string GetId() const OVERRIDE { return agent_host_->GetId(); }
44 virtual std::string GetType() const OVERRIDE {
45 switch (agent_host_->GetType()) {
46 case content::DevToolsAgentHost::TYPE_WEB_CONTENTS:
47 return kTargetTypePage;
48 case content::DevToolsAgentHost::TYPE_SERVICE_WORKER:
49 return kTargetTypeServiceWorker;
53 return kTargetTypeOther;
55 virtual std::string GetTitle() const OVERRIDE {
56 return agent_host_->GetTitle();
58 virtual std::string GetDescription() const OVERRIDE { return std::string(); }
59 virtual GURL GetURL() const OVERRIDE { return agent_host_->GetURL(); }
60 virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; }
61 virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
62 return last_activity_time_;
64 virtual std::string GetParentId() const OVERRIDE { return std::string(); }
65 virtual bool IsAttached() const OVERRIDE {
66 return agent_host_->IsAttached();
68 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
71 virtual bool Activate() const OVERRIDE;
72 virtual bool Close() const OVERRIDE;
75 GURL GetFaviconDataURL(WebContents* web_contents) const;
77 scoped_refptr<DevToolsAgentHost> agent_host_;
81 base::TimeTicks last_activity_time_;
84 Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
85 : agent_host_(agent_host) {
86 if (content::WebContents* web_contents = agent_host_->GetWebContents()) {
87 content::NavigationController& controller = web_contents->GetController();
88 content::NavigationEntry* entry = controller.GetActiveEntry();
89 if (entry != NULL && entry->GetURL().is_valid())
90 favicon_url_ = entry->GetFavicon().url;
91 if (favicon_url_.is_empty())
92 favicon_url_ = GetFaviconDataURL(web_contents);
93 last_activity_time_ = web_contents->GetLastActiveTime();
97 GURL Target::GetFaviconDataURL(WebContents* web_contents) const {
98 // Convert icon image to "data:" url.
99 xwalk::Runtime* runtime =
100 static_cast<xwalk::Runtime*>(web_contents->GetDelegate());
101 if (!runtime || runtime->app_icon().IsEmpty())
103 scoped_refptr<base::RefCountedMemory> icon_bytes =
104 runtime->app_icon().Copy1xPNGBytes();
106 str_url.append(reinterpret_cast<const char*>(icon_bytes->front()),
108 base::Base64Encode(str_url, &str_url);
109 str_url.insert(0, "data:image/png;base64,");
110 return GURL(str_url);
113 bool Target::Activate() const {
114 return agent_host_->Activate();
117 bool Target::Close() const {
118 return agent_host_->Close();
126 Runtime* CreateWithDefaultWindow(
127 RuntimeContext* runtime_context, const GURL& url,
128 Runtime::Observer* observer = NULL) {
129 Runtime* runtime = Runtime::Create(runtime_context, observer);
130 runtime->LoadURL(url);
131 #if !defined(OS_ANDROID)
132 RuntimeUIStrategy ui_strategy;
133 NativeAppWindow::CreateParams params;
134 ui_strategy.Show(runtime, params);
140 XWalkDevToolsHttpHandlerDelegate::XWalkDevToolsHttpHandlerDelegate() {
143 XWalkDevToolsHttpHandlerDelegate::~XWalkDevToolsHttpHandlerDelegate() {
146 std::string XWalkDevToolsHttpHandlerDelegate::GetDiscoveryPageHTML() {
147 return ResourceBundle::GetSharedInstance().GetRawDataResource(
148 IDR_DEVTOOLS_FRONTEND_PAGE_HTML).as_string();
151 void XWalkDevToolsDelegate::ProcessAndSaveThumbnail(
153 scoped_refptr<base::RefCountedBytes> png) {
154 const std::vector<unsigned char>& png_data = png->data();
155 std::string png_string_data(reinterpret_cast<const char*>(&png_data[0]),
157 thumbnail_map_[url] = png_string_data;
160 bool XWalkDevToolsHttpHandlerDelegate::BundlesFrontendResources() {
164 base::FilePath XWalkDevToolsHttpHandlerDelegate::GetDebugFrontendDir() {
165 return base::FilePath();
168 scoped_ptr<net::StreamListenSocket>
169 XWalkDevToolsHttpHandlerDelegate::CreateSocketForTethering(
170 net::StreamListenSocket::Delegate* delegate,
172 return scoped_ptr<net::StreamListenSocket>();
175 XWalkDevToolsDelegate::XWalkDevToolsDelegate(RuntimeContext* runtime_context)
176 : runtime_context_(runtime_context),
177 weak_factory_(this) {
180 XWalkDevToolsDelegate::~XWalkDevToolsDelegate() {
183 base::DictionaryValue* XWalkDevToolsDelegate::HandleCommand(
184 content::DevToolsAgentHost* agent_host,
185 base::DictionaryValue* command_dict) {
189 std::string XWalkDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
190 if (thumbnail_map_.find(url) != thumbnail_map_.end())
191 return thumbnail_map_[url];
192 // TODO(YangangHan): Support real time thumbnail.
193 content::DevToolsAgentHost::List agents =
194 content::DevToolsAgentHost::GetOrCreateAll();
195 for (auto& it : agents) {
196 WebContents* web_contents = it.get()->GetWebContents();
197 if (web_contents && web_contents->GetURL() == url) {
198 RenderWidgetHostView* render_widget_host_view =
199 web_contents->GetRenderViewHost()->GetView();
200 gfx::Rect snapshot_bounds(
201 render_widget_host_view->GetViewBounds().size());
202 ui::GrabViewSnapshotAsync(
203 render_widget_host_view->GetNativeView(),
205 base::ThreadTaskRunnerHandle::Get(),
206 base::Bind(&XWalkDevToolsDelegate::ProcessAndSaveThumbnail,
207 weak_factory_.GetWeakPtr(),
212 return std::string();
215 scoped_ptr<content::DevToolsTarget>
216 XWalkDevToolsDelegate::CreateNewTarget(const GURL& url) {
217 Runtime* runtime = CreateWithDefaultWindow(
218 runtime_context_, GURL(url::kAboutBlankURL));
219 return scoped_ptr<content::DevToolsTarget>(
220 new Target(DevToolsAgentHost::GetOrCreateFor(runtime->web_contents())));
223 void XWalkDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
225 content::DevToolsAgentHost::List agents =
226 content::DevToolsAgentHost::GetOrCreateAll();
227 for (content::DevToolsAgentHost::List::iterator it = agents.begin();
228 it != agents.end(); ++it) {
229 #if !defined(OS_ANDROID)
231 static_cast<Runtime*>((*it)->GetWebContents()->GetDelegate());
232 if (runtime && runtime->remote_debugging_enabled())
234 targets.push_back(new Target(*it));
236 callback.Run(targets);