Upstream version 11.39.260.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / devtools / xwalk_devtools_delegate.cc
index fb77a53..3df59c7 100644 (file)
@@ -6,37 +6,56 @@
 
 #include <string>
 
+#include "base/base64.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/devtools_target.h"
 #include "content/public/browser/favicon_status.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "grit/xwalk_resources.h"
 #include "net/socket/tcp_listen_socket.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "xwalk/runtime/browser/runtime.h"
+#include "ui/snapshot/snapshot.h"
 
 using content::DevToolsAgentHost;
 using content::RenderViewHost;
+using content::RenderWidgetHostView;
 using content::WebContents;
 
 namespace {
 
 const char kTargetTypePage[] = "page";
+const char kTargetTypeServiceWorker[] = "service_worker";
+const char kTargetTypeOther[] = "other";
 
 class Target : public content::DevToolsTarget {
  public:
-  explicit Target(WebContents* web_contents);
+  explicit Target(scoped_refptr<content::DevToolsAgentHost> agent_host);
 
-  virtual std::string GetId() const OVERRIDE { return id_; }
-  virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
-  virtual std::string GetTitle() const OVERRIDE { return title_; }
+  virtual std::string GetId() const OVERRIDE { return agent_host_->GetId(); }
+  virtual std::string GetType() const OVERRIDE {
+      switch (agent_host_->GetType()) {
+        case content::DevToolsAgentHost::TYPE_WEB_CONTENTS:
+           return kTargetTypePage;
+         case content::DevToolsAgentHost::TYPE_SERVICE_WORKER:
+           return kTargetTypeServiceWorker;
+         default:
+           break;
+       }
+       return kTargetTypeOther;
+     }
+  virtual std::string GetTitle() const OVERRIDE {
+    return agent_host_->GetTitle();
+  }
   virtual std::string GetDescription() const OVERRIDE { return std::string(); }
-  virtual GURL GetURL() const OVERRIDE { return url_; }
+  virtual GURL GetURL() const OVERRIDE { return  agent_host_->GetURL(); }
   virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; }
   virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
     return last_activity_time_;
@@ -52,98 +71,186 @@ class Target : public content::DevToolsTarget {
   virtual bool Close() const OVERRIDE;
 
  private:
+  GURL GetFaviconDataURL(WebContents* web_contents) const;
+
   scoped_refptr<DevToolsAgentHost> agent_host_;
   std::string id_;
   std::string title_;
-  GURL url_;
   GURL favicon_url_;
   base::TimeTicks last_activity_time_;
 };
 
-Target::Target(WebContents* web_contents) {
-  agent_host_ =
-      DevToolsAgentHost::GetOrCreateFor(web_contents);
-  id_ = agent_host_->GetId();
-  title_ = base::UTF16ToUTF8(web_contents->GetTitle());
-  url_ = web_contents->GetURL();
-  content::NavigationController& controller = web_contents->GetController();
-  content::NavigationEntry* entry = controller.GetActiveEntry();
-  if (entry != NULL && entry->GetURL().is_valid())
-    favicon_url_ = entry->GetFavicon().url;
-  last_activity_time_ = web_contents->GetLastActiveTime();
+Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
+    : agent_host_(agent_host) {
+  if (content::WebContents* web_contents = agent_host_->GetWebContents()) {
+    content::NavigationController& controller = web_contents->GetController();
+    content::NavigationEntry* entry = controller.GetActiveEntry();
+    if (entry != NULL && entry->GetURL().is_valid())
+      favicon_url_ = entry->GetFavicon().url;
+    if (favicon_url_.is_empty())
+      favicon_url_ = GetFaviconDataURL(web_contents);
+    last_activity_time_ = web_contents->GetLastActiveTime();
+  }
+}
+
+GURL Target::GetFaviconDataURL(WebContents* web_contents) const {
+  // Convert icon image to "data:" url.
+#if defined(OS_ANDROID)
+  // TODO(YangangHan): Add a new base parent class of WebContents
+  // for both Tizen and Android, so we can remove the current macro
+  // in the future.
+  return GURL();
+#endif
+  xwalk::Runtime* runtime =
+      static_cast<xwalk::Runtime*>(web_contents->GetDelegate());
+  if (!runtime || runtime->app_icon().IsEmpty())
+    return GURL();
+  scoped_refptr<base::RefCountedMemory> icon_bytes =
+      runtime->app_icon().Copy1xPNGBytes();
+  std::string str_url;
+  str_url.append(reinterpret_cast<const char*>(icon_bytes->front()),
+                 icon_bytes->size());
+  base::Base64Encode(str_url, &str_url);
+  str_url.insert(0, "data:image/png;base64,");
+  return GURL(str_url);
 }
 
 bool Target::Activate() const {
-  WebContents* web_contents = agent_host_->GetWebContents();
-  if (!web_contents)
-    return false;
-  web_contents->GetDelegate()->ActivateContents(web_contents);
-  return true;
+  return agent_host_->Activate();
 }
 
 bool Target::Close() const {
-  RenderViewHost* rvh = agent_host_->GetWebContents()->GetRenderViewHost();
-  if (!rvh)
-    return false;
-  rvh->ClosePage();
-  return true;
+  return agent_host_->Close();
 }
 
 }  // namespace
 
 namespace xwalk {
 
-XWalkDevToolsDelegate::XWalkDevToolsDelegate(RuntimeContext* runtime_context)
-    : runtime_context_(runtime_context) {
+namespace {
+Runtime* CreateWithDefaultWindow(
+    XWalkBrowserContext* browser_context, const GURL& url,
+    Runtime::Observer* observer) {
+  Runtime* runtime = Runtime::Create(browser_context);
+  runtime->set_observer(observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  runtime->set_ui_delegate(DefaultRuntimeUIDelegate::Create(runtime));
+  runtime->Show();
+#endif
+  return runtime;
 }
+}  // namespace
 
-XWalkDevToolsDelegate::~XWalkDevToolsDelegate() {
+XWalkDevToolsHttpHandlerDelegate::XWalkDevToolsHttpHandlerDelegate() {
+}
+
+XWalkDevToolsHttpHandlerDelegate::~XWalkDevToolsHttpHandlerDelegate() {
 }
 
-std::string XWalkDevToolsDelegate::GetDiscoveryPageHTML() {
+std::string XWalkDevToolsHttpHandlerDelegate::GetDiscoveryPageHTML() {
   return ResourceBundle::GetSharedInstance().GetRawDataResource(
       IDR_DEVTOOLS_FRONTEND_PAGE_HTML).as_string();
 }
 
-bool XWalkDevToolsDelegate::BundlesFrontendResources() {
+void XWalkDevToolsDelegate::ProcessAndSaveThumbnail(
+    const GURL& url,
+    scoped_refptr<base::RefCountedBytes> png) {
+  const std::vector<unsigned char>& png_data = png->data();
+  std::string png_string_data(reinterpret_cast<const char*>(&png_data[0]),
+                              png_data.size());
+  thumbnail_map_[url] = png_string_data;
+}
+
+bool XWalkDevToolsHttpHandlerDelegate::BundlesFrontendResources() {
   return true;
 }
 
-base::FilePath XWalkDevToolsDelegate::GetDebugFrontendDir() {
+base::FilePath XWalkDevToolsHttpHandlerDelegate::GetDebugFrontendDir() {
   return base::FilePath();
 }
 
+scoped_ptr<net::StreamListenSocket>
+XWalkDevToolsHttpHandlerDelegate::CreateSocketForTethering(
+    net::StreamListenSocket::Delegate* delegate,
+    std::string* name) {
+  return scoped_ptr<net::StreamListenSocket>();
+}
+
+XWalkDevToolsDelegate::XWalkDevToolsDelegate(XWalkBrowserContext* context)
+    : browser_context_(context),
+      weak_factory_(this) {
+}
+
+XWalkDevToolsDelegate::~XWalkDevToolsDelegate() {
+}
+
+base::DictionaryValue* XWalkDevToolsDelegate::HandleCommand(
+    content::DevToolsAgentHost* agent_host,
+    base::DictionaryValue* command_dict) {
+  return NULL;
+}
+
 std::string XWalkDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
+  if (thumbnail_map_.find(url) != thumbnail_map_.end())
+    return thumbnail_map_[url];
+  // TODO(YangangHan): Support real time thumbnail.
+  content::DevToolsAgentHost::List agents =
+      content::DevToolsAgentHost::GetOrCreateAll();
+  for (auto& it : agents) {
+    WebContents* web_contents = it.get()->GetWebContents();
+    if (web_contents && web_contents->GetURL() == url) {
+      RenderWidgetHostView* render_widget_host_view =
+          web_contents->GetRenderWidgetHostView();
+      if (!render_widget_host_view)
+        continue;
+      gfx::Rect snapshot_bounds(
+        render_widget_host_view->GetViewBounds().size());
+      ui::GrabViewSnapshotAsync(
+        render_widget_host_view->GetNativeView(),
+        snapshot_bounds,
+        base::ThreadTaskRunnerHandle::Get(),
+        base::Bind(&XWalkDevToolsDelegate::ProcessAndSaveThumbnail,
+                   weak_factory_.GetWeakPtr(),
+                   url));
+        break;
+    }
+  }
   return std::string();
 }
 
 scoped_ptr<content::DevToolsTarget>
 XWalkDevToolsDelegate::CreateNewTarget(const GURL& url) {
-  Runtime* runtime = Runtime::CreateWithDefaultWindow(
-      runtime_context_, GURL(url::kAboutBlankURL));
+  Runtime* runtime = CreateWithDefaultWindow(
+      browser_context_, GURL(url::kAboutBlankURL), this);
   return scoped_ptr<content::DevToolsTarget>(
-      new Target(runtime->web_contents()));
+      new Target(DevToolsAgentHost::GetOrCreateFor(runtime->web_contents())));
 }
 
 void XWalkDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
   TargetList targets;
-  std::vector<WebContents*> web_contents_list =
-      content::DevToolsAgentHost::GetInspectableWebContents();
-  for (std::vector<WebContents*>::iterator it = web_contents_list.begin();
-       it != web_contents_list.end();
-       ++it) {
-    Runtime* runtime = static_cast<Runtime*>((*it)->GetDelegate());
+  content::DevToolsAgentHost::List agents =
+      content::DevToolsAgentHost::GetOrCreateAll();
+  for (content::DevToolsAgentHost::List::iterator it = agents.begin();
+       it != agents.end(); ++it) {
+#if !defined(OS_ANDROID)
+    Runtime* runtime =
+        static_cast<Runtime*>((*it)->GetWebContents()->GetDelegate());
     if (runtime && runtime->remote_debugging_enabled())
+#endif
       targets.push_back(new Target(*it));
   }
   callback.Run(targets);
 }
 
-scoped_ptr<net::StreamListenSocket>
-XWalkDevToolsDelegate::CreateSocketForTethering(
-      net::StreamListenSocket::Delegate* delegate,
-      std::string* name) {
-  return scoped_ptr<net::StreamListenSocket>();
+void XWalkDevToolsDelegate::OnNewRuntimeAdded(Runtime* runtime) {
+  runtime->set_observer(this);
+  runtime->set_ui_delegate(DefaultRuntimeUIDelegate::Create(runtime));
+  runtime->Show();
+}
+
+void XWalkDevToolsDelegate::OnRuntimeClosed(Runtime* runtime) {
+  delete runtime;
 }
 
 }  // namespace xwalk