// 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 <stddef.h>

#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/scoped_observer.h"
#include "base/stl_util.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/devtools/devtools_target_impl.h"
#include "chrome/browser/devtools/global_confirm_info_bar.h"
#include "chrome/browser/extensions/api/debugger/debugger_api_constants.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.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/common/content_client.h"
#include "content/public/common/url_utils.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/switches.h"
#include "ui/base/l10n/l10n_util.h"

using content::DevToolsAgentHost;
using content::RenderProcessHost;
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;

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 extensions {
class ExtensionRegistry;
class ExtensionDevToolsClientHost;

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:
  ExtensionDevToolsInfoBarDelegate(const base::Closure& dismissed_callback,
                                   const std::string& client_name);
  ~ExtensionDevToolsInfoBarDelegate() override;

  // ConfirmInfoBarDelegate:
  Type GetInfoBarType() const override;
  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
  bool ShouldExpire(const NavigationDetails& details) const override;
  void InfoBarDismissed() override;
  base::string16 GetMessageText() const override;
  int GetButtons() const override;
  bool Cancel() override;

  std::string client_name_;
  base::Closure dismissed_callback_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate);
};

ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate(
    const base::Closure& dismissed_callback,
    const std::string& client_name)
    : ConfirmInfoBarDelegate(),
      client_name_(client_name),
      dismissed_callback_(dismissed_callback) {}

ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() {
}

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

infobars::InfoBarDelegate::InfoBarIdentifier
ExtensionDevToolsInfoBarDelegate::GetIdentifier() const {
  return EXTENSION_DEV_TOOLS_INFOBAR_DELEGATE;
}

bool ExtensionDevToolsInfoBarDelegate::ShouldExpire(
    const NavigationDetails& details) const {
  return false;
}

void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() {
  DCHECK(!dismissed_callback_.is_null());
  // Use ResetAndReturn() since running the callback may delete |this|.
  base::ResetAndReturn(&dismissed_callback_).Run();
}

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

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

bool ExtensionDevToolsInfoBarDelegate::Cancel() {
  InfoBarDismissed();
  // InfoBarDismissed() will have closed us already.
  return false;
}

// ExtensionDevToolsInfoBar ---------------------------------------------------

class ExtensionDevToolsInfoBar;
using ExtensionInfoBars =
    std::map<std::string, ExtensionDevToolsInfoBar*>;
base::LazyInstance<ExtensionInfoBars>::Leaky g_extension_info_bars =
    LAZY_INSTANCE_INITIALIZER;

class ExtensionDevToolsInfoBar {
 public:
  static ExtensionDevToolsInfoBar* Create(
      const std::string& extension_id,
      const std::string& extension_name,
      ExtensionDevToolsClientHost* client_host,
      const base::Closure& dismissed_callback);
  void Remove(ExtensionDevToolsClientHost* client_host);

 private:
  ExtensionDevToolsInfoBar(const std::string& extension_id,
                           const std::string& extension_name);
  ~ExtensionDevToolsInfoBar();
  void InfoBarDismissed();

  std::string extension_id_;
  std::map<ExtensionDevToolsClientHost*, base::Closure> callbacks_;
  base::WeakPtr<GlobalConfirmInfoBar> infobar_;
};

// static
ExtensionDevToolsInfoBar* ExtensionDevToolsInfoBar::Create(
      const std::string& extension_id,
      const std::string& extension_name,
      ExtensionDevToolsClientHost* client_host,
      const base::Closure& dismissed_callback) {
  ExtensionInfoBars::iterator it =
      g_extension_info_bars.Get().find(extension_id);
  ExtensionDevToolsInfoBar* infobar = nullptr;
  if (it != g_extension_info_bars.Get().end())
    infobar = it->second;
  else
    infobar = new ExtensionDevToolsInfoBar(extension_id, extension_name);
  infobar->callbacks_[client_host] = dismissed_callback;
  return infobar;
}

ExtensionDevToolsInfoBar::ExtensionDevToolsInfoBar(
    const std::string& extension_id,
    const std::string& extension_name)
    : extension_id_(extension_id) {
  g_extension_info_bars.Get()[extension_id] = this;

  // This class closes the |infobar_|, so it's safe to pass Unretained(this).
  std::unique_ptr<ExtensionDevToolsInfoBarDelegate> delegate(
      new ExtensionDevToolsInfoBarDelegate(
          base::Bind(&ExtensionDevToolsInfoBar::InfoBarDismissed,
                     base::Unretained(this)),
          extension_name));
  infobar_ = GlobalConfirmInfoBar::Show(std::move(delegate));
}

ExtensionDevToolsInfoBar::~ExtensionDevToolsInfoBar() {
  g_extension_info_bars.Get().erase(extension_id_);
  if (infobar_)
    infobar_->Close();
}

void ExtensionDevToolsInfoBar::Remove(
    ExtensionDevToolsClientHost* client_host) {
  callbacks_.erase(client_host);
  if (!callbacks_.size())
    delete this;
}

void ExtensionDevToolsInfoBar::InfoBarDismissed() {
  std::map<ExtensionDevToolsClientHost*, base::Closure> copy = callbacks_;
  for (const auto& pair: copy)
    pair.second.Run();
}

}  // namespace

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

using AttachedClientHosts = std::set<ExtensionDevToolsClientHost*>;
base::LazyInstance<AttachedClientHosts>::Leaky g_attached_client_hosts =
    LAZY_INSTANCE_INITIALIZER;

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

  ~ExtensionDevToolsClientHost() override;

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

  // Closes connection as terminated by the user.
  void InfoBarDismissed();

  // DevToolsAgentHostClient interface.
  void AgentHostClosed(DevToolsAgentHost* agent_host,
                       bool replaced_with_another_client) override;
  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
                               const std::string& message) override;

 private:
  using PendingRequests =
      std::map<int, scoped_refptr<DebuggerSendCommandFunction>>;

  void SendDetachedEvent();

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

  // ExtensionRegistryObserver implementation.
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionInfo::Reason reason) override;

  Profile* profile_;
  scoped_refptr<DevToolsAgentHost> agent_host_;
  std::string extension_id_;
  Debuggee debuggee_;
  content::NotificationRegistrar registrar_;
  int last_request_id_;
  PendingRequests pending_requests_;
  ExtensionDevToolsInfoBar* infobar_;
  api::debugger::DetachReason detach_reason_;

  // Listen to extension unloaded notification.
  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
      extension_registry_observer_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost);
};

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

ExtensionDevToolsClientHost::ExtensionDevToolsClientHost(
    Profile* profile,
    DevToolsAgentHost* agent_host,
    const std::string& extension_id,
    const std::string& extension_name,
    const Debuggee& debuggee)
    : profile_(profile),
      agent_host_(agent_host),
      extension_id_(extension_id),
      last_request_id_(0),
      infobar_(nullptr),
      detach_reason_(api::debugger::DETACH_REASON_TARGET_CLOSED),
      extension_registry_observer_(this) {
  CopyDebuggee(&debuggee_, debuggee);

  g_attached_client_hosts.Get().insert(this);

  // ExtensionRegistryObserver listen extension unloaded and detach debugger
  // from there.
  extension_registry_observer_.Add(ExtensionRegistry::Get(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.
  agent_host_->AttachClient(this);

  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          ::switches::kSilentDebuggerExtensionAPI)) {
    infobar_ = ExtensionDevToolsInfoBar::Create(
        extension_id, extension_name, this,
        base::Bind(&ExtensionDevToolsClientHost::InfoBarDismissed,
                   base::Unretained(this)));
  }
}

ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() {
  if (infobar_)
    infobar_->Remove(this);
  g_attached_client_hosts.Get().erase(this);
}

// DevToolsAgentHostClient implementation.
void ExtensionDevToolsClientHost::AgentHostClosed(
    DevToolsAgentHost* agent_host, bool replaced_with_another_client) {
  DCHECK(agent_host == agent_host_.get());
  if (replaced_with_another_client)
    detach_reason_ = api::debugger::DETACH_REASON_REPLACED_WITH_DEVTOOLS;
  SendDetachedEvent();
  delete this;
}

void ExtensionDevToolsClientHost::Close() {
  agent_host_->DetachClient();
  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);
  agent_host_->DispatchProtocolMessage(json_args);
}

void ExtensionDevToolsClientHost::InfoBarDismissed() {
  detach_reason_ = api::debugger::DETACH_REASON_CANCELED_BY_USER;
  SendDetachedEvent();
  Close();
}

void ExtensionDevToolsClientHost::SendDetachedEvent() {
  if (!EventRouter::Get(profile_))
    return;

  std::unique_ptr<base::ListValue> args(
      OnDetach::Create(debuggee_, detach_reason_));
  std::unique_ptr<Event> event(new Event(
      events::DEBUGGER_ON_DETACH, OnDetach::kEventName, std::move(args)));
  event->restrict_to_browser_context = profile_;
  EventRouter::Get(profile_)
      ->DispatchEventToExtension(extension_id_, std::move(event));
}

void ExtensionDevToolsClientHost::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionInfo::Reason reason) {
  if (extension->id() == extension_id_)
    Close();
}

void ExtensionDevToolsClientHost::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
  Close();
}

void ExtensionDevToolsClientHost::DispatchProtocolMessage(
    DevToolsAgentHost* agent_host, const std::string& message) {
  DCHECK(agent_host == agent_host_.get());
  if (!EventRouter::Get(profile_))
    return;

  std::unique_ptr<base::Value> result = base::JSONReader::Read(message);
  if (!result || !result->IsType(base::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);

    std::unique_ptr<base::ListValue> args(
        OnEvent::Create(debuggee_, method_name, params));
    std::unique_ptr<Event> event(new Event(
        events::DEBUGGER_ON_EVENT, OnEvent::kEventName, std::move(args)));
    event->restrict_to_browser_context = profile_;
    EventRouter::Get(profile_)
        ->DispatchEventToExtension(extension_id_, std::move(event));
  } 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,
                                               GetProfile(),
                                               include_incognito(),
                                               NULL,
                                               NULL,
                                               &web_contents,
                                               NULL);
    if (result && web_contents) {
      // TODO(rdevlin.cronin) This should definitely be GetLastCommittedURL().
      GURL url = web_contents->GetVisibleURL();
      if (PermissionsData::IsRestrictedUrl(url, extension(), &error_))
        return false;
      agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
    }
  } else if (debuggee_.extension_id) {
    ExtensionHost* extension_host =
        ProcessManager::Get(GetProfile())
            ->GetBackgroundHostForExtension(*debuggee_.extension_id);
    if (extension_host) {
      if (PermissionsData::IsRestrictedUrl(extension_host->GetURL(),
                                           extension(),
                                           &error_)) {
        return false;
      }
      agent_host_ =
          DevToolsAgentHost::GetOrCreateFor(extension_host->host_contents());
    }
  } else if (debuggee_.target_id) {
    agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id);
    if (agent_host_.get()) {
      if (PermissionsData::IsRestrictedUrl(agent_host_->GetURL(),
                                           extension(),
                                           &error_)) {
        agent_host_ = nullptr;
        return false;
      }
    }
  } else {
    error_ = keys::kInvalidTargetError;
    return false;
  }

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

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

  const std::string& extension_id = extension()->id();
  DevToolsAgentHost* agent_host = agent_host_.get();
  AttachedClientHosts& hosts = g_attached_client_hosts.Get();
  AttachedClientHosts::iterator it = std::find_if(
      hosts.begin(), hosts.end(),
      [&agent_host, &extension_id](ExtensionDevToolsClientHost* client_host) {
        return client_host->agent_host() == agent_host &&
               client_host->extension_id() == extension_id;
      });

  if (it == hosts.end()) {
    FormatErrorMessage(keys::kNotAttachedError);
    return false;
  }

  client_host_ = *it;
  return true;
}


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

DebuggerAttachFunction::DebuggerAttachFunction() {
}

DebuggerAttachFunction::~DebuggerAttachFunction() {
}

bool DebuggerAttachFunction::RunAsync() {
  std::unique_ptr<Attach::Params> params(Attach::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

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

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

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

  new ExtensionDevToolsClientHost(GetProfile(), agent_host_.get(),
                                  extension()->id(), extension()->name(),
                                  debuggee_);
  SendResponse(true);
  return true;
}


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

DebuggerDetachFunction::DebuggerDetachFunction() {
}

DebuggerDetachFunction::~DebuggerDetachFunction() {
}

bool DebuggerDetachFunction::RunAsync() {
  std::unique_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::RunAsync() {
  std::unique_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) {
  base::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";

base::Value* SerializeTarget(const DevToolsTargetImpl& target) {
  base::DictionaryValue* dictionary = new base::DictionaryValue();

  dictionary->SetString(kTargetIdField, target.GetId());
  dictionary->SetString(kTargetTitleField, target.GetTitle());
  dictionary->SetBoolean(kTargetAttachedField, target.IsAttached());
  dictionary->SetString(kTargetUrlField, target.GetURL().spec());

  std::string type = target.GetType();
  if (type == kTargetTypePage) {
    dictionary->SetInteger(kTargetTabIdField, target.GetTabId());
  } else if (type == kTargetTypeBackgroundPage) {
    dictionary->SetString(kTargetExtensionIdField, target.GetExtensionId());
  } else if (type != kTargetTypeWorker) {
    // DevToolsTargetImpl may support more types than the debugger API.
    type = kTargetTypeOther;
  }
  dictionary->SetString(kTargetTypeField, type);

  GURL favicon_url = target.GetFaviconURL();
  if (favicon_url.is_valid())
    dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec());

  return dictionary;
}

}  // namespace

DebuggerGetTargetsFunction::DebuggerGetTargetsFunction() {
}

DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() {
}

bool DebuggerGetTargetsFunction::RunAsync() {
  std::vector<DevToolsTargetImpl*> list = DevToolsTargetImpl::EnumerateAll();
  content::BrowserThread::PostTask(
      content::BrowserThread::UI,
      FROM_HERE,
      base::Bind(&DebuggerGetTargetsFunction::SendTargetList, this, list));
  return true;
}

void DebuggerGetTargetsFunction::SendTargetList(
    const std::vector<DevToolsTargetImpl*>& target_list) {
  std::unique_ptr<base::ListValue> result(new base::ListValue());
  for (size_t i = 0; i < target_list.size(); ++i)
    result->Append(SerializeTarget(*target_list[i]));
  STLDeleteContainerPointers(target_list.begin(), target_list.end());
  SetResult(std::move(result));
  SendResponse(true);
}

}  // namespace extensions
