// Copyright (c) 2013 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.

#include "content/browser/webrtc/webrtc_internals.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/service_manager_connection.h"
#include "device/wake_lock/public/interfaces/wake_lock_provider.mojom.h"
#include "ipc/ipc_platform_file.h"
#include "media/audio/audio_manager.h"
#include "media/media_features.h"
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"

#if defined(OS_WIN)
#define IntToStringType base::IntToString16
#else
#define IntToStringType base::IntToString
#endif

using base::ProcessId;
using std::string;

namespace content {

namespace {

base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals =
    LAZY_INSTANCE_INITIALIZER;

// Makes sure that |dict| has a ListValue under path "log".
base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
  base::ListValue* log = NULL;
  if (!dict->GetList("log", &log))
    log = dict->SetList("log", base::MakeUnique<base::ListValue>());
  return log;
}

// Removes the log entry associated with a given record.
void FreeLogList(base::Value* value) {
  DCHECK(value->IsType(base::Value::Type::DICTIONARY));
  auto* dict = static_cast<base::DictionaryValue*>(value);
  dict->Remove("log", nullptr);
}

}  // namespace

WebRTCInternals::PendingUpdate::PendingUpdate(
    const char* command,
    std::unique_ptr<base::Value> value)
    : command_(command), value_(std::move(value)) {}

WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other)
    : command_(other.command_),
      value_(std::move(other.value_)) {}

WebRTCInternals::PendingUpdate::~PendingUpdate() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

const char* WebRTCInternals::PendingUpdate::command() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return command_;
}

const base::Value* WebRTCInternals::PendingUpdate::value() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return value_.get();
}

WebRTCInternals::WebRTCInternals() : WebRTCInternals(500, true) {}

WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
                                 bool should_block_power_saving)
    : audio_debug_recordings_(false),
      event_log_recordings_(false),
      selecting_event_log_(false),
      num_open_connections_(0),
      should_block_power_saving_(should_block_power_saving),
      aggregate_updates_ms_(aggregate_updates_ms),
      weak_factory_(this) {
// TODO(grunell): Shouldn't all the webrtc_internals* files be excluded from the
// build if WebRTC is disabled?
#if BUILDFLAG(ENABLE_WEBRTC)
  audio_debug_recordings_file_path_ =
      GetContentClient()->browser()->GetDefaultDownloadDirectory();
  event_log_recordings_file_path_ = audio_debug_recordings_file_path_;

  if (audio_debug_recordings_file_path_.empty()) {
    // In this case the default path (|audio_debug_recordings_file_path_|) will
    // be empty and the platform default path will be used in the file dialog
    // (with no default file name). See SelectFileDialog::SelectFile. On Android
    // where there's no dialog we'll fail to open the file.
    VLOG(1) << "Could not get the download directory.";
  } else {
    audio_debug_recordings_file_path_ =
        audio_debug_recordings_file_path_.Append(
            FILE_PATH_LITERAL("audio_debug"));
    event_log_recordings_file_path_ =
        event_log_recordings_file_path_.Append(FILE_PATH_LITERAL("event_log"));
  }
#endif  // BUILDFLAG(ENABLE_WEBRTC)
}

WebRTCInternals::~WebRTCInternals() {
}

WebRTCInternals* WebRTCInternals::GetInstance() {
  return g_webrtc_internals.Pointer();
}

void WebRTCInternals::OnAddPeerConnection(int render_process_id,
                                          ProcessId pid,
                                          int lid,
                                          const string& url,
                                          const string& rtc_configuration,
                                          const string& constraints) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(tommi): Consider changing this design so that webrtc-internals has
  // minimal impact if chrome://webrtc-internals isn't open.

  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetInteger("rid", render_process_id);
  dict->SetInteger("pid", static_cast<int>(pid));
  dict->SetInteger("lid", lid);
  dict->SetString("rtcConfiguration", rtc_configuration);
  dict->SetString("constraints", constraints);
  dict->SetString("url", url);
  dict->SetBoolean("isOpen", true);

  if (observers_.might_have_observers())
    SendUpdate("addPeerConnection", dict->CreateDeepCopy());

  peer_connection_data_.Append(std::move(dict));
  ++num_open_connections_;
  UpdateWakeLock();

  if (render_process_id_set_.insert(render_process_id).second) {
    RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
    if (host)
      host->AddObserver(this);
  }
}

void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  size_t index;
  base::DictionaryValue* dict = FindRecord(pid, lid, &index);
  if (dict) {
    MaybeClosePeerConnection(dict);
    peer_connection_data_.Remove(index, NULL);
  }

  if (observers_.might_have_observers()) {
    std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue());
    id->SetInteger("pid", static_cast<int>(pid));
    id->SetInteger("lid", lid);
    SendUpdate("removePeerConnection", std::move(id));
  }
}

void WebRTCInternals::OnUpdatePeerConnection(
    ProcessId pid, int lid, const string& type, const string& value) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::DictionaryValue* record = FindRecord(pid, lid);
  if (!record)
    return;

  if (type == "stop")
    MaybeClosePeerConnection(record);

  // Don't update entries if there aren't any observers.
  if (!observers_.might_have_observers())
    return;

  auto log_entry = base::MakeUnique<base::DictionaryValue>();

  double epoch_time = base::Time::Now().ToJsTime();
  string time = base::DoubleToString(epoch_time);
  log_entry->SetString("time", time);
  log_entry->SetString("type", type);
  log_entry->SetString("value", value);

  auto update = base::MakeUnique<base::DictionaryValue>();
  update->SetInteger("pid", static_cast<int>(pid));
  update->SetInteger("lid", lid);
  update->MergeDictionary(log_entry.get());

  SendUpdate("updatePeerConnection", std::move(update));

  // Append the update to the end of the log.
  EnsureLogList(record)->Append(std::move(log_entry));
}

void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
                                 const base::ListValue& value) {
  if (!observers_.might_have_observers())
    return;

  auto dict = base::MakeUnique<base::DictionaryValue>();
  dict->SetInteger("pid", static_cast<int>(pid));
  dict->SetInteger("lid", lid);

  dict->Set("reports", base::MakeUnique<base::Value>(value));

  SendUpdate("addStats", std::move(dict));
}

void WebRTCInternals::OnGetUserMedia(int rid,
                                     base::ProcessId pid,
                                     const std::string& origin,
                                     bool audio,
                                     bool video,
                                     const std::string& audio_constraints,
                                     const std::string& video_constraints) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto dict = base::MakeUnique<base::DictionaryValue>();
  dict->SetInteger("rid", rid);
  dict->SetInteger("pid", static_cast<int>(pid));
  dict->SetString("origin", origin);
  if (audio)
    dict->SetString("audio", audio_constraints);
  if (video)
    dict->SetString("video", video_constraints);

  if (observers_.might_have_observers())
    SendUpdate("addGetUserMedia", dict->CreateDeepCopy());

  get_user_media_requests_.Append(std::move(dict));

  if (render_process_id_set_.insert(rid).second) {
    RenderProcessHost* host = RenderProcessHost::FromID(rid);
    if (host)
      host->AddObserver(this);
  }
}

void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.AddObserver(observer);
}

void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.RemoveObserver(observer);
  if (observers_.might_have_observers())
    return;

  // Disables event log and audio debug recordings if enabled and the last
  // webrtc-internals page is going away.
  DisableAudioDebugRecordings();
  DisableEventLogRecordings();

  // TODO(tommi): Consider removing all the peer_connection_data_.
  for (auto& dictionary : peer_connection_data_)
    FreeLogList(&dictionary);
}

void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (peer_connection_data_.GetSize() > 0)
    observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_);

  for (const auto& request : get_user_media_requests_) {
    observer->OnUpdate("addGetUserMedia", &request);
  }
}

void WebRTCInternals::EnableAudioDebugRecordings(
    content::WebContents* web_contents) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(ENABLE_WEBRTC)
#if defined(OS_ANDROID)
  EnableAudioDebugRecordingsOnAllRenderProcessHosts();
#else
  selecting_event_log_ = false;
  DCHECK(!select_file_dialog_);
  select_file_dialog_ = ui::SelectFileDialog::Create(this, NULL);
  select_file_dialog_->SelectFile(
      ui::SelectFileDialog::SELECT_SAVEAS_FILE,
      base::string16(),
      audio_debug_recordings_file_path_,
      NULL,
      0,
      FILE_PATH_LITERAL(""),
      web_contents->GetTopLevelNativeWindow(),
      NULL);
#endif
#endif
}

void WebRTCInternals::DisableAudioDebugRecordings() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(ENABLE_WEBRTC)
  if (!audio_debug_recordings_)
    return;

  audio_debug_recordings_ = false;

  // Tear down the dialog since the user has unchecked the audio debug
  // recordings box.
  select_file_dialog_ = nullptr;

  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    i.GetCurrentValue()->DisableAudioDebugRecordings();
  }

  // It's safe to get the AudioManager pointer here. That pointer is invalidated
  // on the UI thread, which we're on.
  // AudioManager is deleted on the audio thread, and the AudioManager outlives
  // this object, so it's safe to post unretained to the audio thread.
  media::AudioManager* audio_manager = media::AudioManager::Get();
  audio_manager->GetTaskRunner()->PostTask(
      FROM_HERE, base::Bind(&media::AudioManager::DisableOutputDebugRecording,
                            base::Unretained(audio_manager)));
#endif
}

bool WebRTCInternals::IsAudioDebugRecordingsEnabled() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return audio_debug_recordings_;
}

const base::FilePath& WebRTCInternals::GetAudioDebugRecordingsFilePath() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return audio_debug_recordings_file_path_;
}

void WebRTCInternals::EnableEventLogRecordings(
    content::WebContents* web_contents) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(ENABLE_WEBRTC)
#if defined(OS_ANDROID)
  EnableEventLogRecordingsOnAllRenderProcessHosts();
#else
  DCHECK(web_contents);
  DCHECK(!select_file_dialog_);
  selecting_event_log_ = true;
  select_file_dialog_ = ui::SelectFileDialog::Create(this, nullptr);
  select_file_dialog_->SelectFile(
      ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(),
      event_log_recordings_file_path_, nullptr, 0, FILE_PATH_LITERAL(""),
      web_contents->GetTopLevelNativeWindow(), nullptr);
#endif
#endif
}

void WebRTCInternals::DisableEventLogRecordings() {
#if BUILDFLAG(ENABLE_WEBRTC)
  event_log_recordings_ = false;
  // Tear down the dialog since the user has unchecked the event log checkbox.
  select_file_dialog_ = nullptr;
  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    i.GetCurrentValue()->StopWebRTCEventLog();
#endif
}

bool WebRTCInternals::IsEventLogRecordingsEnabled() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return event_log_recordings_;
}

const base::FilePath& WebRTCInternals::GetEventLogFilePath() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return event_log_recordings_file_path_;
}

void WebRTCInternals::SendUpdate(const char* command,
                                 std::unique_ptr<base::Value> value) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(observers_.might_have_observers());

  bool queue_was_empty = pending_updates_.empty();
  pending_updates_.push(PendingUpdate(command, std::move(value)));

  if (queue_was_empty) {
    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&WebRTCInternals::ProcessPendingUpdates,
                   weak_factory_.GetWeakPtr()),
                   base::TimeDelta::FromMilliseconds(aggregate_updates_ms_));
  }
}

void WebRTCInternals::RenderProcessExited(RenderProcessHost* host,
                                          base::TerminationStatus status,
                                          int exit_code) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  OnRendererExit(host->GetID());
  render_process_id_set_.erase(host->GetID());
  host->RemoveObserver(this);
}

void WebRTCInternals::FileSelected(const base::FilePath& path,
                                   int /* unused_index */,
                                   void* /*unused_params */) {
#if BUILDFLAG(ENABLE_WEBRTC)
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (selecting_event_log_) {
    event_log_recordings_file_path_ = path;
    EnableEventLogRecordingsOnAllRenderProcessHosts();
  } else {
    audio_debug_recordings_file_path_ = path;
    EnableAudioDebugRecordingsOnAllRenderProcessHosts();
  }
#endif
}

void WebRTCInternals::FileSelectionCanceled(void* params) {
#if BUILDFLAG(ENABLE_WEBRTC)
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (selecting_event_log_) {
    SendUpdate("eventLogRecordingsFileSelectionCancelled", nullptr);
  } else {
    SendUpdate("audioDebugRecordingsFileSelectionCancelled", nullptr);
  }
#endif
}

void WebRTCInternals::OnRendererExit(int render_process_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Iterates from the end of the list to remove the PeerConnections created
  // by the exitting renderer.
  for (int i = peer_connection_data_.GetSize() - 1; i >= 0; --i) {
    base::DictionaryValue* record = NULL;
    peer_connection_data_.GetDictionary(i, &record);

    int this_rid = 0;
    record->GetInteger("rid", &this_rid);

    if (this_rid == render_process_id) {
      if (observers_.might_have_observers()) {
        int lid = 0, pid = 0;
        record->GetInteger("lid", &lid);
        record->GetInteger("pid", &pid);

        std::unique_ptr<base::DictionaryValue> update(
            new base::DictionaryValue());
        update->SetInteger("lid", lid);
        update->SetInteger("pid", pid);
        SendUpdate("removePeerConnection", std::move(update));
      }
      MaybeClosePeerConnection(record);
      peer_connection_data_.Remove(i, NULL);
    }
  }
  UpdateWakeLock();

  bool found_any = false;
  // Iterates from the end of the list to remove the getUserMedia requests
  // created by the exiting renderer.
  for (int i = get_user_media_requests_.GetSize() - 1; i >= 0; --i) {
    base::DictionaryValue* record = NULL;
    get_user_media_requests_.GetDictionary(i, &record);

    int this_rid = 0;
    record->GetInteger("rid", &this_rid);

    if (this_rid == render_process_id) {
      get_user_media_requests_.Remove(i, NULL);
      found_any = true;
    }
  }

  if (found_any && observers_.might_have_observers()) {
    std::unique_ptr<base::DictionaryValue> update(new base::DictionaryValue());
    update->SetInteger("rid", render_process_id);
    SendUpdate("removeGetUserMediaForRenderer", std::move(update));
  }
}

#if BUILDFLAG(ENABLE_WEBRTC)
void WebRTCInternals::EnableAudioDebugRecordingsOnAllRenderProcessHosts() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  audio_debug_recordings_ = true;

  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    i.GetCurrentValue()->EnableAudioDebugRecordings(
        audio_debug_recordings_file_path_);
  }

  // It's safe to get the AudioManager pointer here. That pointer is invalidated
  // on the UI thread, which we're on.
  // AudioManager is deleted on the audio thread, and the AudioManager outlives
  // this object, so it's safe to post unretained to the audio thread.
  media::AudioManager* audio_manager = media::AudioManager::Get();
  audio_manager->GetTaskRunner()->PostTask(
      FROM_HERE, base::Bind(&media::AudioManager::EnableOutputDebugRecording,
                            base::Unretained(audio_manager),
                            audio_debug_recordings_file_path_));
}

void WebRTCInternals::EnableEventLogRecordingsOnAllRenderProcessHosts() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  event_log_recordings_ = true;
  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    i.GetCurrentValue()->StartWebRTCEventLog(event_log_recordings_file_path_);
}
#endif

void WebRTCInternals::MaybeClosePeerConnection(base::DictionaryValue* record) {
  bool is_open;
  bool did_read = record->GetBoolean("isOpen", &is_open);
  DCHECK(did_read);
  if (!is_open)
    return;

  record->SetBoolean("isOpen", false);
  --num_open_connections_;
  DCHECK_GE(num_open_connections_, 0);
  UpdateWakeLock();
}

void WebRTCInternals::UpdateWakeLock() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!should_block_power_saving_)
    return;

  if (num_open_connections_ == 0) {
    DVLOG(1)
        << ("Cancel the wake lock on application suspension since no "
            "PeerConnections are active anymore.");
    GetWakeLock()->CancelWakeLock();
  } else if (num_open_connections_ != 0) {
    DVLOG(1) << ("Preventing the application from being suspended while one or "
                 "more PeerConnections are active.");
    GetWakeLock()->RequestWakeLock();
  }
}

device::mojom::WakeLock* WebRTCInternals::GetWakeLock() {
  // Here is a lazy binding, and will not reconnect after connection error.
  if (!wake_lock_) {
    device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
    // In some testing contexts, the service manager connection isn't
    // initialized.
    if (ServiceManagerConnection::GetForProcess()) {
      service_manager::Connector* connector =
          ServiceManagerConnection::GetForProcess()->GetConnector();
      DCHECK(connector);
      device::mojom::WakeLockProviderPtr wake_lock_provider;
      connector->BindInterface(device::mojom::kServiceName,
                               mojo::MakeRequest(&wake_lock_provider));
      wake_lock_provider->GetWakeLockWithoutContext(
          device::mojom::WakeLockType::PreventAppSuspension,
          device::mojom::WakeLockReason::ReasonOther,
          "WebRTC has active PeerConnections", std::move(request));
    }
  }
  return wake_lock_.get();
}

void WebRTCInternals::ProcessPendingUpdates() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  while (!pending_updates_.empty()) {
    const auto& update = pending_updates_.front();
    for (auto& observer : observers_)
      observer.OnUpdate(update.command(), update.value());
    pending_updates_.pop();
  }
}

base::DictionaryValue* WebRTCInternals::FindRecord(
    ProcessId pid,
    int lid,
    size_t* index /*= nullptr*/) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::DictionaryValue* record = nullptr;
  for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) {
    peer_connection_data_.GetDictionary(i, &record);

    int this_pid = 0, this_lid = 0;
    record->GetInteger("pid", &this_pid);
    record->GetInteger("lid", &this_lid);

    if (this_pid == static_cast<int>(pid) && this_lid == lid) {
      if (index)
        *index = i;
      return record;
    }
  }
  return nullptr;
}
}  // namespace content
