// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Implements the Chrome Extensions Debugger API.

#include "chrome/browser/extensions/api/debugger/debugger_api.h"

#include <map>
#include <set>

#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/debugger/debugger_api_constants.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/worker_service.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_utils.h"
#include "extensions/common/error_utils.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

using content::DevToolsAgentHost;
using content::DevToolsClientHost;
using content::DevToolsHttpHandler;
using content::DevToolsManager;
using content::RenderProcessHost;
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;
using content::WorkerService;
using extensions::ErrorUtils;

namespace keys = debugger_api_constants;
namespace Attach = extensions::api::debugger::Attach;
namespace Detach = extensions::api::debugger::Detach;
namespace OnDetach = extensions::api::debugger::OnDetach;
namespace OnEvent = extensions::api::debugger::OnEvent;
namespace SendCommand = extensions::api::debugger::SendCommand;

namespace {
class ExtensionDevToolsInfoBarDelegate;
}  // namespace


// ExtensionDevToolsClientHost ------------------------------------------------

class ExtensionDevToolsClientHost : public DevToolsClientHost,
                                    public content::NotificationObserver {
 public:
  ExtensionDevToolsClientHost(
      Profile* profile,
      DevToolsAgentHost* agent_host,
      const std::string& extension_id,
      const std::string& extension_name,
      const Debuggee& debuggee,
      ExtensionDevToolsInfoBarDelegate* infobar);

  virtual ~ExtensionDevToolsClientHost();

  const std::string& extension_id() { return extension_id_; }
  void Close();
  void SendMessageToBackend(DebuggerSendCommandFunction* function,
                            const std::string& method,
                            SendCommand::Params::CommandParams* command_params);

  // Marks connection as to-be-terminated by the user.
  void MarkAsDismissed();

  // DevToolsClientHost interface
  virtual void InspectedContentsClosing() OVERRIDE;
  virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE;
  virtual void ReplacedWithAnotherClient() OVERRIDE;

 private:
  void SendDetachedEvent();

  // content::NotificationObserver implementation.
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  Profile* profile_;
  scoped_refptr<DevToolsAgentHost> agent_host_;
  std::string extension_id_;
  Debuggee debuggee_;
  content::NotificationRegistrar registrar_;
  int last_request_id_;
  typedef std::map<int, scoped_refptr<DebuggerSendCommandFunction> >
      PendingRequests;
  PendingRequests pending_requests_;
  ExtensionDevToolsInfoBarDelegate* infobar_;
  OnDetach::Reason detach_reason_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost);
};

// The member function declarations come after the other class declarations, so
// they can call members on them.


namespace {

// Helpers --------------------------------------------------------------------

void CopyDebuggee(Debuggee* dst, const Debuggee& src) {
  if (src.tab_id)
    dst->tab_id.reset(new int(*src.tab_id));
  if (src.extension_id)
    dst->extension_id.reset(new std::string(*src.extension_id));
  if (src.target_id)
    dst->target_id.reset(new std::string(*src.target_id));
}


// ExtensionDevToolsInfoBarDelegate -------------------------------------------

class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  // Creates an extension dev tools infobar delegate and adds it to the
  // InfoBarService associated with |rvh|.  Returns the delegate if it was
  // successfully added.
  static ExtensionDevToolsInfoBarDelegate* Create(
      RenderViewHost* rvh,
      const std::string& client_name);

  void set_client_host(ExtensionDevToolsClientHost* client_host) {
    client_host_ = client_host;
  }

 private:
  ExtensionDevToolsInfoBarDelegate(InfoBarService* infobar_service,
                                   const std::string& client_name);
  virtual ~ExtensionDevToolsInfoBarDelegate();

  // ConfirmInfoBarDelegate:
  virtual void InfoBarDismissed() OVERRIDE;
  virtual Type GetInfoBarType() const OVERRIDE;
  virtual bool ShouldExpireInternal(
      const content::LoadCommittedDetails& details) const OVERRIDE;
  virtual string16 GetMessageText() const OVERRIDE;
  virtual int GetButtons() const OVERRIDE;
  virtual bool Cancel() OVERRIDE;

  std::string client_name_;
  ExtensionDevToolsClientHost* client_host_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate);
};

// static
ExtensionDevToolsInfoBarDelegate* ExtensionDevToolsInfoBarDelegate::Create(
    RenderViewHost* rvh,
    const std::string& client_name) {
  if (!rvh)
    return NULL;

  WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
  if (!web_contents)
    return NULL;

  InfoBarService* infobar_service =
      InfoBarService::FromWebContents(web_contents);
  if (!infobar_service)
    return NULL;

  return static_cast<ExtensionDevToolsInfoBarDelegate*>(
      infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
          new ExtensionDevToolsInfoBarDelegate(infobar_service, client_name))));
}

ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate(
    InfoBarService* infobar_service,
    const std::string& client_name)
    : ConfirmInfoBarDelegate(infobar_service),
      client_name_(client_name),
      client_host_(NULL) {
}

ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() {
}

void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() {
  if (client_host_)
    client_host_->MarkAsDismissed();
}

InfoBarDelegate::Type ExtensionDevToolsInfoBarDelegate::GetInfoBarType() const {
  return WARNING_TYPE;
}

bool ExtensionDevToolsInfoBarDelegate::ShouldExpireInternal(
    const content::LoadCommittedDetails& details) const {
  return false;
}

string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL,
                                    UTF8ToUTF16(client_name_));
}

int ExtensionDevToolsInfoBarDelegate::GetButtons() const {
  return BUTTON_CANCEL;
}

bool ExtensionDevToolsInfoBarDelegate::Cancel() {
  InfoBarDismissed();
  return true;
}


// AttachedClientHosts --------------------------------------------------------

class AttachedClientHosts {
 public:
  AttachedClientHosts();
  ~AttachedClientHosts();

  // Returns the singleton instance of this class.
  static AttachedClientHosts* GetInstance();

  void Add(ExtensionDevToolsClientHost* client_host);
  void Remove(ExtensionDevToolsClientHost* client_host);
  ExtensionDevToolsClientHost* Lookup(DevToolsAgentHost* agent_host,
                                      const std::string& extension_id);

 private:
  typedef std::set<ExtensionDevToolsClientHost*> ClientHosts;
  ClientHosts client_hosts_;

  DISALLOW_COPY_AND_ASSIGN(AttachedClientHosts);
};

AttachedClientHosts::AttachedClientHosts() {
}

AttachedClientHosts::~AttachedClientHosts() {
}

// static
AttachedClientHosts* AttachedClientHosts::GetInstance() {
  return Singleton<AttachedClientHosts>::get();
}

void AttachedClientHosts::Add(ExtensionDevToolsClientHost* client_host) {
  client_hosts_.insert(client_host);
}

void AttachedClientHosts::Remove(ExtensionDevToolsClientHost* client_host) {
  client_hosts_.erase(client_host);
}

ExtensionDevToolsClientHost* AttachedClientHosts::Lookup(
    DevToolsAgentHost* agent_host,
    const std::string& extension_id) {
  DevToolsManager* manager = DevToolsManager::GetInstance();
  for (ClientHosts::iterator it = client_hosts_.begin();
       it != client_hosts_.end(); ++it) {
    ExtensionDevToolsClientHost* client_host = *it;
    if (manager->GetDevToolsAgentHostFor(client_host) == agent_host &&
        client_host->extension_id() == extension_id)
      return client_host;
  }
  return NULL;
}

}  // namespace


// ExtensionDevToolsClientHost ------------------------------------------------

ExtensionDevToolsClientHost::ExtensionDevToolsClientHost(
    Profile* profile,
    DevToolsAgentHost* agent_host,
    const std::string& extension_id,
    const std::string& extension_name,
    const Debuggee& debuggee,
    ExtensionDevToolsInfoBarDelegate* infobar)
    : profile_(profile),
      agent_host_(agent_host),
      extension_id_(extension_id),
      last_request_id_(0),
      infobar_(infobar),
      detach_reason_(OnDetach::REASON_TARGET_CLOSED) {
  CopyDebuggee(&debuggee_, debuggee);

  AttachedClientHosts::GetInstance()->Add(this);

  // Detach from debugger when extension unloads.
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
                 content::Source<Profile>(profile_));

  // RVH-based agents disconnect from their clients when the app is terminating
  // but shared worker-based agents do not.
  // Disconnect explicitly to make sure that |this| observer is not leaked.
  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
                 content::NotificationService::AllSources());

  // Attach to debugger and tell it we are ready.
  DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
      agent_host_.get(), this);

  if (infobar_) {
    infobar_->set_client_host(this);
    registrar_.Add(
        this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
        content::Source<InfoBarService>(InfoBarService::FromWebContents(
            WebContents::FromRenderViewHost(
                agent_host_->GetRenderViewHost()))));
  }
}

ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() {
  // Ensure calling RemoveInfoBar() below won't result in Observe() trying to
  // Close() us.
  registrar_.RemoveAll();

  if (infobar_) {
    infobar_->set_client_host(NULL);
    InfoBarService::FromWebContents(WebContents::FromRenderViewHost(
        agent_host_->GetRenderViewHost()))->RemoveInfoBar(infobar_);
  }
  AttachedClientHosts::GetInstance()->Remove(this);
}

// DevToolsClientHost interface
void ExtensionDevToolsClientHost::InspectedContentsClosing() {
  SendDetachedEvent();
  delete this;
}

void ExtensionDevToolsClientHost::ReplacedWithAnotherClient() {
  detach_reason_ = OnDetach::REASON_REPLACED_WITH_DEVTOOLS;
}

void ExtensionDevToolsClientHost::Close() {
  DevToolsManager::GetInstance()->ClientHostClosing(this);
  delete this;
}

void ExtensionDevToolsClientHost::SendMessageToBackend(
    DebuggerSendCommandFunction* function,
    const std::string& method,
    SendCommand::Params::CommandParams* command_params) {
  base::DictionaryValue protocol_request;
  int request_id = ++last_request_id_;
  pending_requests_[request_id] = function;
  protocol_request.SetInteger("id", request_id);
  protocol_request.SetString("method", method);
  if (command_params) {
    protocol_request.Set("params",
                         command_params->additional_properties.DeepCopy());
  }

  std::string json_args;
  base::JSONWriter::Write(&protocol_request, &json_args);
  DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args);
}

void ExtensionDevToolsClientHost::MarkAsDismissed() {
  detach_reason_ = OnDetach::REASON_CANCELED_BY_USER;
}

void ExtensionDevToolsClientHost::SendDetachedEvent() {
  if (!extensions::ExtensionSystem::Get(profile_)->event_router())
    return;

  scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee_,
                                                    detach_reason_));
  scoped_ptr<extensions::Event> event(new extensions::Event(
      OnDetach::kEventName, args.Pass()));
  event->restrict_to_profile = profile_;
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      DispatchEventToExtension(extension_id_, event.Pass());
}

void ExtensionDevToolsClientHost::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
    if (content::Details<extensions::UnloadedExtensionInfo>(details)->
        extension->id() == extension_id_)
      Close();
  } else if (type == chrome::NOTIFICATION_APP_TERMINATING) {
    Close();
  } else {
    DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
    if (content::Details<InfoBarRemovedDetails>(details)->first == infobar_) {
      infobar_ = NULL;
      SendDetachedEvent();
      Close();
    }
  }
}

void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend(
    const std::string& message) {
  if (!extensions::ExtensionSystem::Get(profile_)->event_router())
    return;

  scoped_ptr<Value> result(base::JSONReader::Read(message));
  if (!result->IsType(Value::TYPE_DICTIONARY))
    return;
  base::DictionaryValue* dictionary =
      static_cast<base::DictionaryValue*>(result.get());

  int id;
  if (!dictionary->GetInteger("id", &id)) {
    std::string method_name;
    if (!dictionary->GetString("method", &method_name))
      return;

    OnEvent::Params params;
    base::DictionaryValue* params_value;
    if (dictionary->GetDictionary("params", &params_value))
      params.additional_properties.Swap(params_value);

    scoped_ptr<ListValue> args(OnEvent::Create(debuggee_, method_name, params));
    scoped_ptr<extensions::Event> event(new extensions::Event(
        OnEvent::kEventName, args.Pass()));
    event->restrict_to_profile = profile_;
    extensions::ExtensionSystem::Get(profile_)->event_router()->
        DispatchEventToExtension(extension_id_, event.Pass());
  } else {
    DebuggerSendCommandFunction* function = pending_requests_[id].get();
    if (!function)
      return;

    function->SendResponseBody(dictionary);
    pending_requests_.erase(id);
  }
}


// DebuggerFunction -----------------------------------------------------------

DebuggerFunction::DebuggerFunction()
    : client_host_(NULL) {
}

DebuggerFunction::~DebuggerFunction() {
}

void DebuggerFunction::FormatErrorMessage(const std::string& format) {
  if (debuggee_.tab_id)
    error_ = ErrorUtils::FormatErrorMessage(
      format, keys::kTabTargetType, base::IntToString(*debuggee_.tab_id));
  else if (debuggee_.extension_id)
    error_ = ErrorUtils::FormatErrorMessage(
      format, keys::kBackgroundPageTargetType, *debuggee_.extension_id);
  else
    error_ = ErrorUtils::FormatErrorMessage(
      format, keys::kOpaqueTargetType, *debuggee_.target_id);
}

bool DebuggerFunction::InitAgentHost() {
  if (debuggee_.tab_id) {
    WebContents* web_contents = NULL;
    bool result = ExtensionTabUtil::GetTabById(
        *debuggee_.tab_id, profile(), include_incognito(), NULL, NULL,
        &web_contents, NULL);
    if (result && web_contents) {
      if (content::HasWebUIScheme(web_contents->GetURL())) {
        error_ = ErrorUtils::FormatErrorMessage(
            keys::kAttachToWebUIError,
            web_contents->GetURL().scheme());
        return false;
      }
      agent_host_ = DevToolsAgentHost::GetOrCreateFor(
          web_contents->GetRenderViewHost());
    }
  } else if (debuggee_.extension_id) {
    extensions::ExtensionHost* extension_host =
        extensions::ExtensionSystem::Get(profile())->process_manager()->
            GetBackgroundHostForExtension(*debuggee_.extension_id);
    if (extension_host) {
      agent_host_ = DevToolsAgentHost::GetOrCreateFor(
          extension_host->render_view_host());
    }
  } else if (debuggee_.target_id) {
    agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id);
  } else {
    error_ = keys::kInvalidTargetError;
    return false;
  }

  if (!agent_host_.get()) {
    FormatErrorMessage(keys::kNoTargetError);
    return false;
  }
  return true;
}

bool DebuggerFunction::InitClientHost() {
  if (!InitAgentHost())
    return false;

  client_host_ = AttachedClientHosts::GetInstance()->Lookup(
      agent_host_.get(), GetExtension()->id());

  if (!client_host_) {
    FormatErrorMessage(keys::kNotAttachedError);
    return false;
  }
  return true;
}


// DebuggerAttachFunction -----------------------------------------------------

DebuggerAttachFunction::DebuggerAttachFunction() {
}

DebuggerAttachFunction::~DebuggerAttachFunction() {
}

bool DebuggerAttachFunction::RunImpl() {
  scoped_ptr<Attach::Params> params(Attach::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  CopyDebuggee(&debuggee_, params->target);
  if (!InitAgentHost())
    return false;

  if (!DevToolsHttpHandler::IsSupportedProtocolVersion(
          params->required_version)) {
    error_ = ErrorUtils::FormatErrorMessage(
        keys::kProtocolVersionNotSupportedError,
        params->required_version);
    return false;
  }

  if (agent_host_->IsAttached()) {
    FormatErrorMessage(keys::kAlreadyAttachedError);
    return false;
  }

  ExtensionDevToolsInfoBarDelegate* infobar = NULL;
  if (!CommandLine::ForCurrentProcess()->
       HasSwitch(switches::kSilentDebuggerExtensionAPI)) {
    // Do not attach to the target if for any reason the infobar cannot be shown
    // for this WebContents instance.
    infobar = ExtensionDevToolsInfoBarDelegate::Create(
          agent_host_->GetRenderViewHost(), GetExtension()->name());
    if (!infobar) {
      error_ = ErrorUtils::FormatErrorMessage(
          keys::kSilentDebuggingRequired,
          switches::kSilentDebuggerExtensionAPI);
      return false;
    }
  }

  new ExtensionDevToolsClientHost(profile(), agent_host_.get(),
                                  GetExtension()->id(), GetExtension()->name(),
                                  debuggee_, infobar);
  SendResponse(true);
  return true;
}


// DebuggerDetachFunction -----------------------------------------------------

DebuggerDetachFunction::DebuggerDetachFunction() {
}

DebuggerDetachFunction::~DebuggerDetachFunction() {
}

bool DebuggerDetachFunction::RunImpl() {
  scoped_ptr<Detach::Params> params(Detach::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  CopyDebuggee(&debuggee_, params->target);
  if (!InitClientHost())
    return false;

  client_host_->Close();
  SendResponse(true);
  return true;
}


// DebuggerSendCommandFunction ------------------------------------------------

DebuggerSendCommandFunction::DebuggerSendCommandFunction() {
}

DebuggerSendCommandFunction::~DebuggerSendCommandFunction() {
}

bool DebuggerSendCommandFunction::RunImpl() {
  scoped_ptr<SendCommand::Params> params(SendCommand::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  CopyDebuggee(&debuggee_, params->target);
  if (!InitClientHost())
    return false;

  client_host_->SendMessageToBackend(this, params->method,
      params->command_params.get());
  return true;
}

void DebuggerSendCommandFunction::SendResponseBody(
    base::DictionaryValue* response) {
  Value* error_body;
  if (response->Get("error", &error_body)) {
    base::JSONWriter::Write(error_body, &error_);
    SendResponse(false);
    return;
  }

  base::DictionaryValue* result_body;
  SendCommand::Results::Result result;
  if (response->GetDictionary("result", &result_body))
    result.additional_properties.Swap(result_body);

  results_ = SendCommand::Results::Create(result);
  SendResponse(true);
}


// DebuggerGetTargetsFunction -------------------------------------------------

namespace {

const char kTargetIdField[] = "id";
const char kTargetTypeField[] = "type";
const char kTargetTitleField[] = "title";
const char kTargetAttachedField[] = "attached";
const char kTargetUrlField[] = "url";
const char kTargetFaviconUrlField[] = "faviconUrl";
const char kTargetTypePage[] = "page";
const char kTargetTypeBackgroundPage[] = "background_page";
const char kTargetTypeWorker[] = "worker";
const char kTargetTypeOther[] = "other";
const char kTargetTabIdField[] = "tabId";
const char kTargetExtensionIdField[] = "extensionId";

extensions::ExtensionHost*
    GetExtensionBackgroundHost(WebContents* web_contents) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  if (!profile)
    return NULL;

  extensions::ExtensionHost* extension_host =
      extensions::ExtensionSystem::Get(profile)->process_manager()->
          GetBackgroundHostForExtension(web_contents->GetURL().host());

  return (extension_host && extension_host->host_contents() == web_contents) ?
      extension_host : NULL;
}

base::Value* SerializePageInfo(RenderViewHost* rvh) {
  WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
  if (!web_contents)
    return NULL;

  DevToolsAgentHost* agent_host = DevToolsAgentHost::GetOrCreateFor(rvh);

  base::DictionaryValue* dictionary = new base::DictionaryValue();

  dictionary->SetString(kTargetIdField, agent_host->GetId());
  dictionary->SetBoolean(kTargetAttachedField, agent_host->IsAttached());
  dictionary->SetString(kTargetUrlField, web_contents->GetURL().spec());

  extensions::ExtensionHost* extension_host =
      GetExtensionBackgroundHost(web_contents);
  if (extension_host) {
    // This RenderViewHost belongs to a background page.
    dictionary->SetString(kTargetTypeField, kTargetTypeBackgroundPage);
    dictionary->SetString(kTargetExtensionIdField,
                          extension_host->extension()->id());
    dictionary->SetString(kTargetTitleField,
                          extension_host->extension()->name());
  } else {
    int tab_id = ExtensionTabUtil::GetTabId(web_contents);
    if (tab_id != -1) {
      // This RenderViewHost belongs to a regular page.
      dictionary->SetString(kTargetTypeField, kTargetTypePage);
      dictionary->SetInteger(kTargetTabIdField, tab_id);
    } else {
      dictionary->SetString(kTargetTypeField, kTargetTypeOther);
    }
    dictionary->SetString(kTargetTitleField, web_contents->GetTitle());

    content::NavigationController& controller = web_contents->GetController();
    content::NavigationEntry* entry = controller.GetVisibleEntry();
    if (entry != NULL && entry->GetURL().is_valid()) {
      dictionary->SetString(kTargetFaviconUrlField,
                            entry->GetFavicon().url.spec());
    }
  }

  return dictionary;
}

base::Value* SerializeWorkerInfo(const WorkerService::WorkerInfo& worker) {
  base::DictionaryValue* dictionary = new base::DictionaryValue;

  scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetForWorker(
      worker.process_id, worker.route_id));
  dictionary->SetString(kTargetIdField, agent->GetId());
  dictionary->SetString(kTargetTypeField, kTargetTypeWorker);
  dictionary->SetString(kTargetTitleField, worker.name);
  dictionary->SetString(kTargetUrlField, worker.url.spec());
  dictionary->SetBoolean(kTargetAttachedField, agent->IsAttached());

  return dictionary;
}

} // namespace

DebuggerGetTargetsFunction::DebuggerGetTargetsFunction() {
}

DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() {
}

bool DebuggerGetTargetsFunction::RunImpl() {
  base::ListValue* results_list = new base::ListValue();

  std::vector<RenderViewHost*> rvh_list =
      DevToolsAgentHost::GetValidRenderViewHosts();
  for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
       it != rvh_list.end(); ++it) {
    base::Value* value = SerializePageInfo(*it);
    if (value)
      results_list->Append(value);
  }

  content::BrowserThread::PostTaskAndReplyWithResult(
      content::BrowserThread::IO,
      FROM_HERE,
      base::Bind(&DebuggerGetTargetsFunction::CollectWorkerInfo, this),
      base::Bind(&DebuggerGetTargetsFunction::SendTargetList, this,
                 results_list));
  return true;
}

DebuggerGetTargetsFunction::WorkerInfoList
DebuggerGetTargetsFunction::CollectWorkerInfo() {
  return WorkerService::GetInstance()->GetWorkers();
}

void DebuggerGetTargetsFunction::SendTargetList(
    base::ListValue* list,
    const WorkerInfoList& worker_info) {
  for (size_t i = 0; i < worker_info.size(); ++i)
    list->Append(SerializeWorkerInfo(worker_info[i]));
  SetResult(list);
  SendResponse(true);
}
