/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Google Inc. nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/peerconnection/RTCPeerConnection.h"

#include <algorithm>
#include <memory>
#include <set>
#include <utility>

#include "base/memory/ptr_util.h"
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/Nullable.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/v8_void_function.h"
#include "bindings/modules/v8/V8MediaStreamTrack.h"
#include "bindings/modules/v8/V8RTCCertificate.h"
#include "bindings/modules/v8/rtc_ice_candidate_init_or_rtc_ice_candidate.h"
#include "bindings/modules/v8/v8_rtc_peer_connection_error_callback.h"
#include "bindings/modules/v8/v8_rtc_session_description_callback.h"
#include "bindings/modules/v8/v8_rtc_stats_callback.h"
#include "core/dom/DOMException.h"
#include "core/dom/DOMTimeStamp.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContext.h"
#include "core/frame/Deprecation.h"
#include "core/frame/HostsUsingFeatures.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameClient.h"
#include "core/frame/UseCounter.h"
#include "modules/crypto/CryptoResultImpl.h"
#include "modules/mediastream/MediaConstraintsImpl.h"
#include "modules/mediastream/MediaStream.h"
#include "modules/mediastream/MediaStreamEvent.h"
#include "modules/peerconnection/RTCAnswerOptions.h"
#include "modules/peerconnection/RTCConfiguration.h"
#include "modules/peerconnection/RTCDTMFSender.h"
#include "modules/peerconnection/RTCDataChannel.h"
#include "modules/peerconnection/RTCDataChannelEvent.h"
#include "modules/peerconnection/RTCDataChannelInit.h"
#include "modules/peerconnection/RTCIceServer.h"
#include "modules/peerconnection/RTCOfferOptions.h"
#include "modules/peerconnection/RTCPeerConnectionIceEvent.h"
#include "modules/peerconnection/RTCRtpReceiver.h"
#include "modules/peerconnection/RTCRtpSender.h"
#include "modules/peerconnection/RTCSessionDescription.h"
#include "modules/peerconnection/RTCSessionDescriptionInit.h"
#include "modules/peerconnection/RTCSessionDescriptionRequestImpl.h"
#include "modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.h"
#include "modules/peerconnection/RTCStatsReport.h"
#include "modules/peerconnection/RTCStatsRequestImpl.h"
#include "modules/peerconnection/RTCTrackEvent.h"
#include "modules/peerconnection/RTCVoidRequestImpl.h"
#include "modules/peerconnection/RTCVoidRequestPromiseImpl.h"
#include "modules/peerconnection/testing/InternalsRTCPeerConnection.h"
#include "platform/InstanceCounters.h"
#include "platform/bindings/Microtask.h"
#include "platform/bindings/ScriptState.h"
#include "platform/bindings/V8ThrowException.h"
#include "platform/peerconnection/RTCAnswerOptionsPlatform.h"
#include "platform/peerconnection/RTCOfferOptionsPlatform.h"
#include "platform/runtime_enabled_features.h"
#include "platform/wtf/Time.h"
#include "public/platform/Platform.h"
#include "public/platform/TaskType.h"
#include "public/platform/WebCryptoAlgorithmParams.h"
#include "public/platform/WebMediaStream.h"
#include "public/platform/WebRTCAnswerOptions.h"
#include "public/platform/WebRTCCertificate.h"
#include "public/platform/WebRTCCertificateGenerator.h"
#include "public/platform/WebRTCConfiguration.h"
#include "public/platform/WebRTCDataChannelHandler.h"
#include "public/platform/WebRTCDataChannelInit.h"
#include "public/platform/WebRTCError.h"
#include "public/platform/WebRTCICECandidate.h"
#include "public/platform/WebRTCKeyParams.h"
#include "public/platform/WebRTCOfferOptions.h"
#include "public/platform/WebRTCSessionDescription.h"
#include "public/platform/WebRTCSessionDescriptionRequest.h"
#include "public/platform/WebRTCStatsRequest.h"
#include "public/platform/WebRTCVoidRequest.h"

namespace blink {

namespace {

const char kSignalingStateClosedMessage[] =
    "The RTCPeerConnection's signalingState is 'closed'.";

// The maximum number of PeerConnections that can exist simultaneously.
const long kMaxPeerConnections = 500;

bool ThrowExceptionIfSignalingStateClosed(
    RTCPeerConnection::SignalingState state,
    ExceptionState& exception_state) {
  if (state == RTCPeerConnection::kSignalingStateClosed) {
    exception_state.ThrowDOMException(kInvalidStateError,
                                      kSignalingStateClosedMessage);
    return true;
  }

  return false;
}

void AsyncCallErrorCallback(V8RTCPeerConnectionErrorCallback* error_callback,
                            DOMException* exception) {
  DCHECK(error_callback);
  Microtask::EnqueueMicrotask(
      WTF::Bind(&V8RTCPeerConnectionErrorCallback::InvokeAndReportException,
                WrapPersistentCallbackFunction(error_callback), nullptr,
                WrapPersistent(exception)));
}

bool CallErrorCallbackIfSignalingStateClosed(
    RTCPeerConnection::SignalingState state,
    V8RTCPeerConnectionErrorCallback* error_callback) {
  if (state == RTCPeerConnection::kSignalingStateClosed) {
    if (error_callback)
      AsyncCallErrorCallback(
          error_callback, DOMException::Create(kInvalidStateError,
                                               kSignalingStateClosedMessage));

    return true;
  }

  return false;
}

bool IsIceCandidateMissingSdp(
    const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
  if (candidate.IsRTCIceCandidateInit()) {
    const RTCIceCandidateInit& ice_candidate_init =
        candidate.GetAsRTCIceCandidateInit();
    return !ice_candidate_init.hasSdpMid() &&
           !ice_candidate_init.hasSdpMLineIndex();
  }

  DCHECK(candidate.IsRTCIceCandidate());
  return false;
}

WebRTCOfferOptions ConvertToWebRTCOfferOptions(const RTCOfferOptions& options) {
  return WebRTCOfferOptions(RTCOfferOptionsPlatform::Create(
      options.hasOfferToReceiveVideo()
          ? std::max(options.offerToReceiveVideo(), 0)
          : -1,
      options.hasOfferToReceiveAudio()
          ? std::max(options.offerToReceiveAudio(), 0)
          : -1,
      options.hasVoiceActivityDetection() ? options.voiceActivityDetection()
                                          : true,
      options.hasIceRestart() ? options.iceRestart() : false));
}

WebRTCAnswerOptions ConvertToWebRTCAnswerOptions(
    const RTCAnswerOptions& options) {
  return WebRTCAnswerOptions(RTCAnswerOptionsPlatform::Create(
      options.hasVoiceActivityDetection() ? options.voiceActivityDetection()
                                          : true));
}

scoped_refptr<WebRTCICECandidate> ConvertToWebRTCIceCandidate(
    ExecutionContext* context,
    const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
  DCHECK(!candidate.IsNull());
  if (candidate.IsRTCIceCandidateInit()) {
    const RTCIceCandidateInit& ice_candidate_init =
        candidate.GetAsRTCIceCandidateInit();
    // TODO(guidou): Change default value to -1. crbug.com/614958.
    unsigned short sdp_m_line_index = 0;
    if (ice_candidate_init.hasSdpMLineIndex()) {
      sdp_m_line_index = ice_candidate_init.sdpMLineIndex();
    } else {
      UseCounter::Count(context,
                        WebFeature::kRTCIceCandidateDefaultSdpMLineIndex);
    }
    return WebRTCICECandidate::Create(ice_candidate_init.candidate(),
                                      ice_candidate_init.sdpMid(),
                                      sdp_m_line_index);
  }

  DCHECK(candidate.IsRTCIceCandidate());
  return candidate.GetAsRTCIceCandidate()->WebCandidate();
}

// Helper class for RTCPeerConnection::generateCertificate.
class WebRTCCertificateObserver : public WebRTCCertificateCallback {
 public:
  // Takes ownership of |resolver|.
  static WebRTCCertificateObserver* Create(ScriptPromiseResolver* resolver) {
    return new WebRTCCertificateObserver(resolver);
  }

  ~WebRTCCertificateObserver() override {}

 private:
  explicit WebRTCCertificateObserver(ScriptPromiseResolver* resolver)
      : resolver_(resolver) {}

  void OnSuccess(std::unique_ptr<WebRTCCertificate> certificate) override {
    resolver_->Resolve(new RTCCertificate(std::move(certificate)));
  }

  void OnError() override { resolver_->Reject(); }

  Persistent<ScriptPromiseResolver> resolver_;
};

WebRTCIceTransportPolicy IceTransportPolicyFromString(const String& policy) {
  if (policy == "relay")
    return WebRTCIceTransportPolicy::kRelay;
  DCHECK_EQ(policy, "all");
  return WebRTCIceTransportPolicy::kAll;
}

WebRTCConfiguration ParseConfiguration(ExecutionContext* context,
                                       const RTCConfiguration& configuration,
                                       ExceptionState& exception_state) {
  DCHECK(context);

  WebRTCIceTransportPolicy ice_transport_policy =
      WebRTCIceTransportPolicy::kAll;
  if (configuration.hasIceTransportPolicy()) {
    UseCounter::Count(context, WebFeature::kRTCConfigurationIceTransportPolicy);
    ice_transport_policy =
        IceTransportPolicyFromString(configuration.iceTransportPolicy());
  } else if (configuration.hasIceTransports()) {
    UseCounter::Count(context, WebFeature::kRTCConfigurationIceTransports);
    ice_transport_policy =
        IceTransportPolicyFromString(configuration.iceTransports());
  }

  WebRTCBundlePolicy bundle_policy = WebRTCBundlePolicy::kBalanced;
  String bundle_policy_string = configuration.bundlePolicy();
  if (bundle_policy_string == "max-compat") {
    bundle_policy = WebRTCBundlePolicy::kMaxCompat;
  } else if (bundle_policy_string == "max-bundle") {
    bundle_policy = WebRTCBundlePolicy::kMaxBundle;
  } else {
    DCHECK_EQ(bundle_policy_string, "balanced");
  }

  WebRTCRtcpMuxPolicy rtcp_mux_policy = WebRTCRtcpMuxPolicy::kRequire;
  String rtcp_mux_policy_string = configuration.rtcpMuxPolicy();
  if (rtcp_mux_policy_string == "negotiate") {
    rtcp_mux_policy = WebRTCRtcpMuxPolicy::kNegotiate;
    Deprecation::CountDeprecation(context, WebFeature::kRtcpMuxPolicyNegotiate);
  } else {
    DCHECK_EQ(rtcp_mux_policy_string, "require");
  }

  WebRTCSdpSemantics sdp_semantics = WebRTCSdpSemantics::kDefault;
  if (configuration.hasSdpSemantics()) {
    String sdp_semantics_string = configuration.sdpSemantics();
    if (sdp_semantics_string == "plan-b") {
      sdp_semantics = WebRTCSdpSemantics::kPlanB;
    } else {
      DCHECK_EQ(sdp_semantics_string, "unified-plan");
      sdp_semantics = WebRTCSdpSemantics::kUnifiedPlan;
    }
  }

  WebRTCConfiguration web_configuration;
  web_configuration.ice_transport_policy = ice_transport_policy;
  web_configuration.bundle_policy = bundle_policy;
  web_configuration.rtcp_mux_policy = rtcp_mux_policy;
  web_configuration.sdp_semantics = sdp_semantics;

  if (configuration.hasIceServers()) {
    Vector<WebRTCIceServer> ice_servers;
    for (const RTCIceServer& ice_server : configuration.iceServers()) {
      Vector<String> url_strings;
      if (ice_server.hasURLs()) {
        UseCounter::Count(context, WebFeature::kRTCIceServerURLs);
        const StringOrStringSequence& urls = ice_server.urls();
        if (urls.IsString()) {
          url_strings.push_back(urls.GetAsString());
        } else {
          DCHECK(urls.IsStringSequence());
          url_strings = urls.GetAsStringSequence();
        }
      } else if (ice_server.hasURL()) {
        UseCounter::Count(context, WebFeature::kRTCIceServerURL);
        url_strings.push_back(ice_server.url());
      } else {
        exception_state.ThrowTypeError("Malformed RTCIceServer");
        return WebRTCConfiguration();
      }

      String username = ice_server.username();
      String credential = ice_server.credential();

      for (const String& url_string : url_strings) {
        KURL url(NullURL(), url_string);
        if (!url.IsValid()) {
          exception_state.ThrowDOMException(
              kSyntaxError, "'" + url_string + "' is not a valid URL.");
          return WebRTCConfiguration();
        }
        if (!(url.ProtocolIs("turn") || url.ProtocolIs("turns") ||
              url.ProtocolIs("stun"))) {
          exception_state.ThrowDOMException(
              kSyntaxError, "'" + url.Protocol() +
                                "' is not one of the supported URL schemes "
                                "'stun', 'turn' or 'turns'.");
          return WebRTCConfiguration();
        }
        if ((url.ProtocolIs("turn") || url.ProtocolIs("turns")) &&
            (username.IsNull() || credential.IsNull())) {
          exception_state.ThrowDOMException(kInvalidAccessError,
                                            "Both username and credential are "
                                            "required when the URL scheme is "
                                            "\"turn\" or \"turns\".");
        }
        ice_servers.push_back(WebRTCIceServer{url, username, credential});
      }
    }
    web_configuration.ice_servers = ice_servers;
  }

  if (configuration.hasCertificates()) {
    const HeapVector<Member<RTCCertificate>>& certificates =
        configuration.certificates();
    WebVector<std::unique_ptr<WebRTCCertificate>> certificates_copy(
        certificates.size());
    for (size_t i = 0; i < certificates.size(); ++i) {
      certificates_copy[i] = certificates[i]->CertificateShallowCopy();
    }
    web_configuration.certificates = std::move(certificates_copy);
  }

  web_configuration.ice_candidate_pool_size =
      configuration.iceCandidatePoolSize();
  return web_configuration;
}

RTCOfferOptionsPlatform* ParseOfferOptions(const Dictionary& options,
                                           ExceptionState& exception_state) {
  if (options.IsUndefinedOrNull())
    return nullptr;

  const Vector<String>& property_names =
      options.GetPropertyNames(exception_state);
  if (exception_state.HadException())
    return nullptr;

  // Treat |options| as MediaConstraints if it is empty or has "optional" or
  // "mandatory" properties for compatibility.
  // TODO(jiayl): remove constraints when RTCOfferOptions reaches Stable and
  // client code is ready.
  if (property_names.IsEmpty() || property_names.Contains("optional") ||
      property_names.Contains("mandatory"))
    return nullptr;

  int32_t offer_to_receive_video = -1;
  int32_t offer_to_receive_audio = -1;
  bool voice_activity_detection = true;
  bool ice_restart = false;

  if (DictionaryHelper::Get(options, "offerToReceiveVideo",
                            offer_to_receive_video) &&
      offer_to_receive_video < 0)
    offer_to_receive_video = 0;
  if (DictionaryHelper::Get(options, "offerToReceiveAudio",
                            offer_to_receive_audio) &&
      offer_to_receive_audio < 0)
    offer_to_receive_audio = 0;
  DictionaryHelper::Get(options, "voiceActivityDetection",
                        voice_activity_detection);
  DictionaryHelper::Get(options, "iceRestart", ice_restart);

  RTCOfferOptionsPlatform* rtc_offer_options = RTCOfferOptionsPlatform::Create(
      offer_to_receive_video, offer_to_receive_audio, voice_activity_detection,
      ice_restart);
  return rtc_offer_options;
}

// Helper class for
// |RTCPeerConnection::getStats(ScriptState*, MediaStreamTrack*)|
class WebRTCStatsReportCallbackResolver : public WebRTCStatsReportCallback {
 public:
  // Takes ownership of |resolver|.
  static std::unique_ptr<WebRTCStatsReportCallback> Create(
      ScriptPromiseResolver* resolver) {
    return std::unique_ptr<WebRTCStatsReportCallback>(
        new WebRTCStatsReportCallbackResolver(resolver));
  }

  ~WebRTCStatsReportCallbackResolver() override {
    DCHECK(
        ExecutionContext::From(resolver_->GetScriptState())->IsContextThread());
  }

 private:
  explicit WebRTCStatsReportCallbackResolver(ScriptPromiseResolver* resolver)
      : resolver_(resolver) {}

  void OnStatsDelivered(std::unique_ptr<WebRTCStatsReport> report) override {
    DCHECK(
        ExecutionContext::From(resolver_->GetScriptState())->IsContextThread());
    resolver_->Resolve(new RTCStatsReport(std::move(report)));
  }

  Persistent<ScriptPromiseResolver> resolver_;
};

}  // namespace

RTCPeerConnection::EventWrapper::EventWrapper(Event* event,
                                              BoolFunction function)
    : event_(event), setup_function_(std::move(function)) {}

bool RTCPeerConnection::EventWrapper::Setup() {
  if (setup_function_) {
    return std::move(setup_function_).Run();
  }
  return true;
}

void RTCPeerConnection::EventWrapper::Trace(blink::Visitor* visitor) {
  visitor->Trace(event_);
}

RTCPeerConnection* RTCPeerConnection::Create(
    ExecutionContext* context,
    const RTCConfiguration& rtc_configuration,
    const Dictionary& media_constraints,
    ExceptionState& exception_state) {
  if (media_constraints.IsObject()) {
    UseCounter::Count(context,
                      WebFeature::kRTCPeerConnectionConstructorConstraints);
  } else {
    UseCounter::Count(context,
                      WebFeature::kRTCPeerConnectionConstructorCompliant);
  }

  WebRTCConfiguration configuration =
      ParseConfiguration(context, rtc_configuration, exception_state);
  if (exception_state.HadException())
    return nullptr;

  // Make sure no certificates have expired.
  if (configuration.certificates.size() > 0) {
    DOMTimeStamp now = ConvertSecondsToDOMTimeStamp(CurrentTime());
    for (const std::unique_ptr<WebRTCCertificate>& certificate :
         configuration.certificates) {
      DOMTimeStamp expires = certificate->Expires();
      if (expires <= now) {
        exception_state.ThrowDOMException(kInvalidAccessError,
                                          "Expired certificate(s).");
        return nullptr;
      }
    }
  }

  MediaErrorState media_error_state;
  WebMediaConstraints constraints = MediaConstraintsImpl::Create(
      context, media_constraints, media_error_state);
  if (media_error_state.HadException()) {
    media_error_state.RaiseException(exception_state);
    return nullptr;
  }

  RTCPeerConnection* peer_connection = new RTCPeerConnection(
      context, configuration, constraints, exception_state);
  peer_connection->PauseIfNeeded();
  if (exception_state.HadException())
    return nullptr;

  return peer_connection;
}

RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
                                     const WebRTCConfiguration& configuration,
                                     WebMediaConstraints constraints,
                                     ExceptionState& exception_state)
    : PausableObject(context),
      signaling_state_(kSignalingStateStable),
      ice_gathering_state_(kICEGatheringStateNew),
      ice_connection_state_(kICEConnectionStateNew),
      // WebRTC spec specifies kNetworking as task source.
      // https://www.w3.org/TR/webrtc/#operation
      dispatch_scheduled_event_runner_(
          AsyncMethodRunner<RTCPeerConnection>::Create(
              this,
              &RTCPeerConnection::DispatchScheduledEvent,
              context->GetTaskRunner(TaskType::kNetworking))),
      stopped_(false),
      closed_(false),
      has_data_channels_(false) {
  Document* document = ToDocument(GetExecutionContext());

  // If we fail, set |m_closed| and |m_stopped| to true, to avoid hitting the
  // assert in the destructor.

  if (InstanceCounters::CounterValue(
          InstanceCounters::kRTCPeerConnectionCounter) >= kMaxPeerConnections) {
    closed_ = true;
    stopped_ = true;
    exception_state.ThrowDOMException(kUnknownError,
                                      "Cannot create so many PeerConnections");
    return;
  }
  InstanceCounters::IncrementCounter(
      InstanceCounters::kRTCPeerConnectionCounter);
  if (!document->GetFrame()) {
    closed_ = true;
    stopped_ = true;
    exception_state.ThrowDOMException(
        kNotSupportedError,
        "PeerConnections may not be created in detached documents.");
    return;
  }

  peer_handler_ = Platform::Current()->CreateRTCPeerConnectionHandler(
      this, document->GetTaskRunner(TaskType::kUnthrottled));
  if (!peer_handler_) {
    closed_ = true;
    stopped_ = true;
    exception_state.ThrowDOMException(kNotSupportedError,
                                      "No PeerConnection handler can be "
                                      "created, perhaps WebRTC is disabled?");
    return;
  }

  document->GetFrame()->Client()->DispatchWillStartUsingPeerConnectionHandler(
      peer_handler_.get());

  if (!peer_handler_->Initialize(configuration, constraints)) {
    closed_ = true;
    stopped_ = true;
    exception_state.ThrowDOMException(
        kNotSupportedError, "Failed to initialize native PeerConnection.");
    return;
  }

  connection_handle_for_scheduler_ =
      document->GetFrame()->FrameScheduler()->OnActiveConnectionCreated();
}

RTCPeerConnection::~RTCPeerConnection() {
  // This checks that close() or stop() is called before the destructor.
  // We are assuming that a wrapper is always created when RTCPeerConnection is
  // created.
  DCHECK(closed_ || stopped_);
  InstanceCounters::DecrementCounter(
      InstanceCounters::kRTCPeerConnectionCounter);
}

void RTCPeerConnection::Dispose() {
  // Promptly clears a raw reference from content/ to an on-heap object
  // so that content/ doesn't access it in a lazy sweeping phase.
  peer_handler_.reset();
}

ScriptPromise RTCPeerConnection::createOffer(ScriptState* script_state,
                                             const RTCOfferOptions& options) {
  if (signaling_state_ == kSignalingStateClosed)
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  RTCSessionDescriptionRequest* request =
      RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
  if (options.hasOfferToReceiveAudio() || options.hasOfferToReceiveVideo()) {
    ExecutionContext* context = ExecutionContext::From(script_state);
    UseCounter::Count(
        context,
        WebFeature::kRTCPeerConnectionCreateOfferOptionsOfferToReceive);
  }
  peer_handler_->CreateOffer(request, ConvertToWebRTCOfferOptions(options));
  return promise;
}

ScriptPromise RTCPeerConnection::createOffer(
    ScriptState* script_state,
    V8RTCSessionDescriptionCallback* success_callback,
    V8RTCPeerConnectionErrorCallback* error_callback,
    const Dictionary& rtc_offer_options,
    ExceptionState& exception_state) {
  DCHECK(success_callback);
  DCHECK(error_callback);
  ExecutionContext* context = ExecutionContext::From(script_state);
  UseCounter::Count(
      context, WebFeature::kRTCPeerConnectionCreateOfferLegacyFailureCallback);
  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
    return ScriptPromise::CastUndefined(script_state);

  RTCOfferOptionsPlatform* offer_options =
      ParseOfferOptions(rtc_offer_options, exception_state);
  if (exception_state.HadException())
    return ScriptPromise();
  RTCSessionDescriptionRequest* request =
      RTCSessionDescriptionRequestImpl::Create(
          GetExecutionContext(), this, success_callback, error_callback);

  if (offer_options) {
    if (offer_options->OfferToReceiveAudio() != -1 ||
        offer_options->OfferToReceiveVideo() != -1) {
      UseCounter::Count(
          context, WebFeature::kRTCPeerConnectionCreateOfferLegacyOfferOptions);
    } else {
      UseCounter::Count(
          context, WebFeature::kRTCPeerConnectionCreateOfferLegacyCompliant);
    }

    peer_handler_->CreateOffer(request, WebRTCOfferOptions(offer_options));
  } else {
    MediaErrorState media_error_state;
    WebMediaConstraints constraints = MediaConstraintsImpl::Create(
        context, rtc_offer_options, media_error_state);
    // Report constraints parsing errors via the callback, but ignore
    // unknown/unsupported constraints as they would be silently discarded by
    // WebIDL.
    if (media_error_state.CanGenerateException()) {
      String error_msg = media_error_state.GetErrorMessage();
      AsyncCallErrorCallback(error_callback,
                             DOMException::Create(kOperationError, error_msg));
      return ScriptPromise::CastUndefined(script_state);
    }

    if (!constraints.IsEmpty()) {
      UseCounter::Count(
          context, WebFeature::kRTCPeerConnectionCreateOfferLegacyConstraints);
    } else {
      UseCounter::Count(
          context, WebFeature::kRTCPeerConnectionCreateOfferLegacyCompliant);
    }

    peer_handler_->CreateOffer(request, constraints);
  }

  return ScriptPromise::CastUndefined(script_state);
}

ScriptPromise RTCPeerConnection::createAnswer(ScriptState* script_state,
                                              const RTCAnswerOptions& options) {
  if (signaling_state_ == kSignalingStateClosed)
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  RTCSessionDescriptionRequest* request =
      RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
  peer_handler_->CreateAnswer(request, ConvertToWebRTCAnswerOptions(options));
  return promise;
}

ScriptPromise RTCPeerConnection::createAnswer(
    ScriptState* script_state,
    V8RTCSessionDescriptionCallback* success_callback,
    V8RTCPeerConnectionErrorCallback* error_callback,
    const Dictionary& media_constraints) {
  DCHECK(success_callback);
  DCHECK(error_callback);
  ExecutionContext* context = ExecutionContext::From(script_state);
  UseCounter::Count(
      context, WebFeature::kRTCPeerConnectionCreateAnswerLegacyFailureCallback);
  if (media_constraints.IsObject()) {
    UseCounter::Count(
        context, WebFeature::kRTCPeerConnectionCreateAnswerLegacyConstraints);
  } else {
    UseCounter::Count(
        context, WebFeature::kRTCPeerConnectionCreateAnswerLegacyCompliant);
  }

  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
    return ScriptPromise::CastUndefined(script_state);

  MediaErrorState media_error_state;
  WebMediaConstraints constraints = MediaConstraintsImpl::Create(
      context, media_constraints, media_error_state);
  // Report constraints parsing errors via the callback, but ignore
  // unknown/unsupported constraints as they would be silently discarded by
  // WebIDL.
  if (media_error_state.CanGenerateException()) {
    String error_msg = media_error_state.GetErrorMessage();
    AsyncCallErrorCallback(error_callback,
                           DOMException::Create(kOperationError, error_msg));
    return ScriptPromise::CastUndefined(script_state);
  }

  RTCSessionDescriptionRequest* request =
      RTCSessionDescriptionRequestImpl::Create(
          GetExecutionContext(), this, success_callback, error_callback);
  peer_handler_->CreateAnswer(request, constraints);
  return ScriptPromise::CastUndefined(script_state);
}

ScriptPromise RTCPeerConnection::setLocalDescription(
    ScriptState* script_state,
    const RTCSessionDescriptionInit& session_description_init) {
  if (signaling_state_ == kSignalingStateClosed)
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
  peer_handler_->SetLocalDescription(
      request, WebRTCSessionDescription(session_description_init.type(),
                                        session_description_init.sdp()));
  return promise;
}

ScriptPromise RTCPeerConnection::setLocalDescription(
    ScriptState* script_state,
    const RTCSessionDescriptionInit& session_description_init,
    V8VoidFunction* success_callback,
    V8RTCPeerConnectionErrorCallback* error_callback) {
  ExecutionContext* context = ExecutionContext::From(script_state);
  if (success_callback && error_callback) {
    UseCounter::Count(
        context,
        WebFeature::kRTCPeerConnectionSetLocalDescriptionLegacyCompliant);
  } else {
    if (!success_callback)
      UseCounter::Count(
          context,
          WebFeature::
              kRTCPeerConnectionSetLocalDescriptionLegacyNoSuccessCallback);
    if (!error_callback)
      UseCounter::Count(
          context,
          WebFeature::
              kRTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback);
  }

  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
    return ScriptPromise::CastUndefined(script_state);

  RTCVoidRequest* request = RTCVoidRequestImpl::Create(
      GetExecutionContext(), this, success_callback, error_callback);
  peer_handler_->SetLocalDescription(
      request, WebRTCSessionDescription(session_description_init.type(),
                                        session_description_init.sdp()));
  return ScriptPromise::CastUndefined(script_state);
}

RTCSessionDescription* RTCPeerConnection::localDescription() {
  WebRTCSessionDescription web_session_description =
      peer_handler_->LocalDescription();
  if (web_session_description.IsNull())
    return nullptr;

  return RTCSessionDescription::Create(web_session_description);
}

ScriptPromise RTCPeerConnection::setRemoteDescription(
    ScriptState* script_state,
    const RTCSessionDescriptionInit& session_description_init) {
  if (signaling_state_ == kSignalingStateClosed)
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
  peer_handler_->SetRemoteDescription(
      request, WebRTCSessionDescription(session_description_init.type(),
                                        session_description_init.sdp()));
  return promise;
}

ScriptPromise RTCPeerConnection::setRemoteDescription(
    ScriptState* script_state,
    const RTCSessionDescriptionInit& session_description_init,
    V8VoidFunction* success_callback,
    V8RTCPeerConnectionErrorCallback* error_callback) {
  ExecutionContext* context = ExecutionContext::From(script_state);
  if (success_callback && error_callback) {
    UseCounter::Count(
        context,
        WebFeature::kRTCPeerConnectionSetRemoteDescriptionLegacyCompliant);
  } else {
    if (!success_callback)
      UseCounter::Count(
          context,
          WebFeature::
              kRTCPeerConnectionSetRemoteDescriptionLegacyNoSuccessCallback);
    if (!error_callback)
      UseCounter::Count(
          context,
          WebFeature::
              kRTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback);
  }

  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
    return ScriptPromise::CastUndefined(script_state);

  RTCVoidRequest* request = RTCVoidRequestImpl::Create(
      GetExecutionContext(), this, success_callback, error_callback);
  peer_handler_->SetRemoteDescription(
      request, WebRTCSessionDescription(session_description_init.type(),
                                        session_description_init.sdp()));
  return ScriptPromise::CastUndefined(script_state);
}

RTCSessionDescription* RTCPeerConnection::remoteDescription() {
  WebRTCSessionDescription web_session_description =
      peer_handler_->RemoteDescription();
  if (web_session_description.IsNull())
    return nullptr;

  return RTCSessionDescription::Create(web_session_description);
}

void RTCPeerConnection::setConfiguration(
    ScriptState* script_state,
    const RTCConfiguration& rtc_configuration,
    ExceptionState& exception_state) {
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return;

  WebRTCConfiguration configuration = ParseConfiguration(
      ExecutionContext::From(script_state), rtc_configuration, exception_state);

  if (exception_state.HadException())
    return;

  MediaErrorState media_error_state;
  if (media_error_state.HadException()) {
    media_error_state.RaiseException(exception_state);
    return;
  }

  WebRTCErrorType error = peer_handler_->SetConfiguration(configuration);
  if (error != WebRTCErrorType::kNone) {
    // All errors besides InvalidModification should have been detected above.
    if (error == WebRTCErrorType::kInvalidModification) {
      exception_state.ThrowDOMException(
          kInvalidModificationError,
          "Attempted to modify the PeerConnection's "
          "configuration in an unsupported way.");
    } else {
      exception_state.ThrowDOMException(
          kOperationError,
          "Could not update the PeerConnection with the given configuration.");
    }
  }
}

ScriptPromise RTCPeerConnection::generateCertificate(
    ScriptState* script_state,
    const AlgorithmIdentifier& keygen_algorithm,
    ExceptionState& exception_state) {
  // Normalize |keygenAlgorithm| with WebCrypto, making sure it is a recognized
  // AlgorithmIdentifier.
  WebCryptoAlgorithm crypto_algorithm;
  AlgorithmError error;
  if (!NormalizeAlgorithm(keygen_algorithm, kWebCryptoOperationGenerateKey,
                          crypto_algorithm, &error)) {
    // Reject generateCertificate with the same error as was produced by
    // WebCrypto. |result| is garbage collected, no need to delete.
    CryptoResultImpl* result = CryptoResultImpl::Create(script_state);
    ScriptPromise promise = result->Promise();
    result->CompleteWithError(error.error_type, error.error_details);
    return promise;
  }

  // Check if |keygenAlgorithm| contains the optional DOMTimeStamp |expires|
  // attribute.
  Nullable<DOMTimeStamp> expires;
  if (keygen_algorithm.IsDictionary()) {
    Dictionary keygen_algorithm_dict = keygen_algorithm.GetAsDictionary();
    if (keygen_algorithm_dict.HasProperty("expires", exception_state)) {
      v8::Local<v8::Value> expires_value;
      keygen_algorithm_dict.Get("expires", expires_value);
      if (expires_value->IsNumber()) {
        double expires_double =
            expires_value
                ->ToNumber(script_state->GetIsolate()->GetCurrentContext())
                .ToLocalChecked()
                ->Value();
        if (expires_double >= 0) {
          expires.Set(static_cast<DOMTimeStamp>(expires_double));
        }
      }
    }
  }
  if (exception_state.HadException()) {
    return ScriptPromise();
  }

  // Convert from WebCrypto representation to recognized WebRTCKeyParams. WebRTC
  // supports a small subset of what are valid AlgorithmIdentifiers.
  const char* unsupported_params_string =
      "The 1st argument provided is an AlgorithmIdentifier with a supported "
      "algorithm name, but the parameters are not supported.";
  Nullable<WebRTCKeyParams> key_params;
  switch (crypto_algorithm.Id()) {
    case kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
      // name: "RSASSA-PKCS1-v1_5"
      unsigned public_exponent;
      // "publicExponent" must fit in an unsigned int. The only recognized
      // "hash" is "SHA-256".
      if (crypto_algorithm.RsaHashedKeyGenParams()
              ->ConvertPublicExponentToUnsigned(public_exponent) &&
          crypto_algorithm.RsaHashedKeyGenParams()->GetHash().Id() ==
              kWebCryptoAlgorithmIdSha256) {
        unsigned modulus_length =
            crypto_algorithm.RsaHashedKeyGenParams()->ModulusLengthBits();
        key_params.Set(
            WebRTCKeyParams::CreateRSA(modulus_length, public_exponent));
      } else {
        return ScriptPromise::RejectWithDOMException(
            script_state, DOMException::Create(kNotSupportedError,
                                               unsupported_params_string));
      }
      break;
    case kWebCryptoAlgorithmIdEcdsa:
      // name: "ECDSA"
      // The only recognized "namedCurve" is "P-256".
      if (crypto_algorithm.EcKeyGenParams()->NamedCurve() ==
          kWebCryptoNamedCurveP256) {
        key_params.Set(WebRTCKeyParams::CreateECDSA(kWebRTCECCurveNistP256));
      } else {
        return ScriptPromise::RejectWithDOMException(
            script_state, DOMException::Create(kNotSupportedError,
                                               unsupported_params_string));
      }
      break;
    default:
      return ScriptPromise::RejectWithDOMException(
          script_state, DOMException::Create(kNotSupportedError,
                                             "The 1st argument provided is an "
                                             "AlgorithmIdentifier, but the "
                                             "algorithm is not supported."));
      break;
  }
  DCHECK(!key_params.IsNull());

  std::unique_ptr<WebRTCCertificateGenerator> certificate_generator =
      Platform::Current()->CreateRTCCertificateGenerator();

  // |keyParams| was successfully constructed, but does the certificate
  // generator support these parameters?
  if (!certificate_generator->IsSupportedKeyParams(key_params.Get())) {
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kNotSupportedError, unsupported_params_string));
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  std::unique_ptr<WebRTCCertificateObserver> certificate_observer(
      WebRTCCertificateObserver::Create(resolver));

  // Generate certificate. The |certificateObserver| will resolve the promise
  // asynchronously upon completion. The observer will manage its own
  // destruction as well as the resolver's destruction.
  scoped_refptr<WebTaskRunner> task_runner =
      ExecutionContext::From(script_state)
          ->GetTaskRunner(blink::TaskType::kUnthrottled);
  if (expires.IsNull()) {
    certificate_generator->GenerateCertificate(
        key_params.Get(), std::move(certificate_observer), task_runner);
  } else {
    certificate_generator->GenerateCertificateWithExpiration(
        key_params.Get(), expires.Get(), std::move(certificate_observer),
        task_runner);
  }

  return promise;
}

ScriptPromise RTCPeerConnection::addIceCandidate(
    ScriptState* script_state,
    const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
  if (signaling_state_ == kSignalingStateClosed)
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));

  if (IsIceCandidateMissingSdp(candidate))
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(
            script_state->GetIsolate(),
            "Candidate missing values for both sdpMid and sdpMLineIndex"));

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
  scoped_refptr<WebRTCICECandidate> web_candidate = ConvertToWebRTCIceCandidate(
      ExecutionContext::From(script_state), candidate);
  bool implemented =
      peer_handler_->AddICECandidate(request, std::move(web_candidate));
  if (!implemented)
    resolver->Reject(DOMException::Create(
        kOperationError, "This operation could not be completed."));

  return promise;
}

ScriptPromise RTCPeerConnection::addIceCandidate(
    ScriptState* script_state,
    const RTCIceCandidateInitOrRTCIceCandidate& candidate,
    V8VoidFunction* success_callback,
    V8RTCPeerConnectionErrorCallback* error_callback) {
  DCHECK(success_callback);
  DCHECK(error_callback);

  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
    return ScriptPromise::CastUndefined(script_state);

  if (IsIceCandidateMissingSdp(candidate))
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(
            script_state->GetIsolate(),
            "Candidate missing values for both sdpMid and sdpMLineIndex"));

  RTCVoidRequest* request = RTCVoidRequestImpl::Create(
      GetExecutionContext(), this, success_callback, error_callback);
  scoped_refptr<WebRTCICECandidate> web_candidate = ConvertToWebRTCIceCandidate(
      ExecutionContext::From(script_state), candidate);
  bool implemented =
      peer_handler_->AddICECandidate(request, std::move(web_candidate));
  if (!implemented)
    AsyncCallErrorCallback(
        error_callback,
        DOMException::Create(kOperationError,
                             "This operation could not be completed."));

  return ScriptPromise::CastUndefined(script_state);
}

String RTCPeerConnection::signalingState() const {
  switch (signaling_state_) {
    case kSignalingStateStable:
      return "stable";
    case kSignalingStateHaveLocalOffer:
      return "have-local-offer";
    case kSignalingStateHaveRemoteOffer:
      return "have-remote-offer";
    case kSignalingStateHaveLocalPrAnswer:
      return "have-local-pranswer";
    case kSignalingStateHaveRemotePrAnswer:
      return "have-remote-pranswer";
    case kSignalingStateClosed:
      return "closed";
  }

  NOTREACHED();
  return String();
}

String RTCPeerConnection::iceGatheringState() const {
  switch (ice_gathering_state_) {
    case kICEGatheringStateNew:
      return "new";
    case kICEGatheringStateGathering:
      return "gathering";
    case kICEGatheringStateComplete:
      return "complete";
  }

  NOTREACHED();
  return String();
}

String RTCPeerConnection::iceConnectionState() const {
  switch (ice_connection_state_) {
    case kICEConnectionStateNew:
      return "new";
    case kICEConnectionStateChecking:
      return "checking";
    case kICEConnectionStateConnected:
      return "connected";
    case kICEConnectionStateCompleted:
      return "completed";
    case kICEConnectionStateFailed:
      return "failed";
    case kICEConnectionStateDisconnected:
      return "disconnected";
    case kICEConnectionStateClosed:
      return "closed";
  }

  NOTREACHED();
  return String();
}

void RTCPeerConnection::addStream(ScriptState* script_state,
                                  MediaStream* stream,
                                  const Dictionary& media_constraints,
                                  ExceptionState& exception_state) {
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return;

  if (!stream) {
    exception_state.ThrowDOMException(
        kTypeMismatchError,
        ExceptionMessages::ArgumentNullOrIncorrectType(1, "MediaStream"));
    return;
  }

  if (local_streams_.Contains(stream))
    return;

  MediaErrorState media_error_state;
  WebMediaConstraints constraints =
      MediaConstraintsImpl::Create(ExecutionContext::From(script_state),
                                   media_constraints, media_error_state);
  if (media_error_state.HadException()) {
    media_error_state.RaiseException(exception_state);
    return;
  }

  local_streams_.push_back(stream);
  stream->RegisterObserver(this);
  for (auto& track : stream->getTracks()) {
    DCHECK(track->Component());
    tracks_.insert(track->Component(), track);
  }

  bool valid = peer_handler_->AddStream(stream->Descriptor(), constraints);
  if (!valid)
    exception_state.ThrowDOMException(kSyntaxError,
                                      "Unable to add the provided stream.");
  // Ensure |rtp_senders_| is up-to-date so that |addTrack| knows if a sender
  // already exists for a track. When |addStream| and |removeStream| are
  // are implemented using |addTrack| and |removeTrack| we can simply add and
  // remove senders there instead. https://crbug.com/738929
  getSenders();
}

void RTCPeerConnection::removeStream(MediaStream* stream,
                                     ExceptionState& exception_state) {
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return;

  if (!stream) {
    exception_state.ThrowDOMException(
        kTypeMismatchError,
        ExceptionMessages::ArgumentNullOrIncorrectType(1, "MediaStream"));
    return;
  }

  size_t pos = local_streams_.Find(stream);
  if (pos == kNotFound)
    return;

  local_streams_.EraseAt(pos);
  stream->UnregisterObserver(this);

  peer_handler_->RemoveStream(stream->Descriptor());
}

MediaStreamVector RTCPeerConnection::getLocalStreams() const {
  // TODO(hbos): We should define this as "the streams of all senders" instead
  // of a set that we add to and subtract from on |addStream| and
  // |removeStream|. https://crbug.com/738918
  return local_streams_;
}

MediaStreamVector RTCPeerConnection::getRemoteStreams() const {
  MediaStreamVector remote_streams;
  for (const auto& rtp_receiver : rtp_receivers_) {
    for (const auto& stream : rtp_receiver->streams()) {
      if (!remote_streams.Contains(stream))
        remote_streams.push_back(stream);
    }
  }
  return remote_streams;
}

MediaStream* RTCPeerConnection::getRemoteStream(
    MediaStreamDescriptor* descriptor) const {
  for (const auto& rtp_receiver : rtp_receivers_) {
    for (const auto& stream : rtp_receiver->streams()) {
      if (stream->Descriptor() == descriptor)
        return stream;
    }
  }
  return nullptr;
}

size_t RTCPeerConnection::getRemoteStreamUsageCount(
    MediaStreamDescriptor* descriptor) const {
  size_t usage_count = 0;
  for (const auto& receiver : rtp_receivers_) {
    WebVector<WebMediaStream> streams = receiver->web_receiver().Streams();
    for (const WebMediaStream& stream : streams) {
      if (stream == descriptor)
        ++usage_count;
    }
  }
  return usage_count;
}

ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
                                          V8RTCStatsCallback* success_callback,
                                          MediaStreamTrack* selector) {
  ExecutionContext* context = ExecutionContext::From(script_state);
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  UseCounter::Count(context,
                    WebFeature::kRTCPeerConnectionGetStatsLegacyNonCompliant);
  RTCStatsRequest* stats_request = RTCStatsRequestImpl::Create(
      GetExecutionContext(), this, success_callback, selector);
  // FIXME: Add passing selector as part of the statsRequest.
  peer_handler_->GetStats(stats_request);

  resolver->Resolve();
  return promise;
}

ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state) {
  ExecutionContext* context = ExecutionContext::From(script_state);
  UseCounter::Count(context, WebFeature::kRTCPeerConnectionGetStats);

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  peer_handler_->GetStats(WebRTCStatsReportCallbackResolver::Create(resolver));

  return promise;
}

HeapVector<Member<RTCRtpSender>> RTCPeerConnection::getSenders() {
  WebVector<std::unique_ptr<WebRTCRtpSender>> web_rtp_senders =
      peer_handler_->GetSenders();
  HeapVector<Member<RTCRtpSender>> rtp_senders(web_rtp_senders.size());
  for (size_t i = 0; i < web_rtp_senders.size(); ++i) {
    uintptr_t id = web_rtp_senders[i]->Id();
    const auto it = rtp_senders_.find(id);
    if (it != rtp_senders_.end()) {
      rtp_senders[i] = it->value;
    } else {
      // There does not exist an |RTCRtpSender| for this |WebRTCRtpSender|
      // yet, create it.
      MediaStreamTrack* track = nullptr;
      if (web_rtp_senders[i]->Track()) {
        track = GetTrack(web_rtp_senders[i]->Track());
        DCHECK(track);
      }
      RTCRtpSender* rtp_sender =
          new RTCRtpSender(std::move(web_rtp_senders[i]), track);
      rtp_senders_.insert(id, rtp_sender);
      rtp_senders[i] = rtp_sender;
    }
  }
  return rtp_senders;
}

HeapVector<Member<RTCRtpReceiver>> RTCPeerConnection::getReceivers() {
  return rtp_receivers_;
}

RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
                                          MediaStreamVector streams,
                                          ExceptionState& exception_state) {
  DCHECK(track);
  DCHECK(track->Component());
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return nullptr;
  if (streams.size() >= 2) {
    // TODO(hbos): Don't throw an exception when this is supported by the lower
    // layers. https://crbug.com/webrtc/7932
    exception_state.ThrowDOMException(
        kNotSupportedError,
        "Adding a track to multiple streams is not supported.");
    return nullptr;
  }
  for (const auto sender_entry : rtp_senders_) {
    RTCRtpSender* sender = sender_entry.value;
    if (sender->track() == track) {
      exception_state.ThrowDOMException(
          kInvalidAccessError, "A sender already exists for the track.");
      return nullptr;
    }
  }

  WebVector<WebMediaStream> web_streams(streams.size());
  for (size_t i = 0; i < streams.size(); ++i) {
    web_streams[i] = streams[i]->Descriptor();
  }
  std::unique_ptr<WebRTCRtpSender> web_rtp_sender =
      peer_handler_->AddTrack(track->Component(), web_streams);
  if (!web_rtp_sender) {
    exception_state.ThrowDOMException(
        kNotSupportedError, "A sender could not be created for this track.");
    return nullptr;
  }

  uintptr_t id = web_rtp_sender->Id();
  DCHECK(rtp_senders_.find(id) == rtp_senders_.end());
  RTCRtpSender* rtp_sender = new RTCRtpSender(std::move(web_rtp_sender), track);
  tracks_.insert(track->Component(), track);
  rtp_senders_.insert(id, rtp_sender);
  return rtp_sender;
}

void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
                                    ExceptionState& exception_state) {
  DCHECK(sender);
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return;
  if (rtp_senders_.find(sender->web_sender()->Id()) == rtp_senders_.end()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The sender was not created by this peer connection.");
    return;
  }

  if (!peer_handler_->RemoveTrack(sender->web_sender())) {
    // Operation aborted. This indicates that the sender is no longer used by
    // the peer connection, i.e. that it was removed due to setting a remote
    // description of type "rollback".
    // Note: Until the WebRTC library supports re-using senders, a sender will
    // also stop being used as a result of being removed.
    return;
  }
  // Successfully removing the track results in the sender's track property
  // being nulled.
  DCHECK(!sender->web_sender()->Track());
  sender->SetTrack(nullptr);
  // TODO(hbos): When |addStream| and |removeStream| are implemented using
  // |addTrack| and |removeTrack|, we should remove |sender| from |rtp_senders_|
  // here. https://crbug.com/738929
}

RTCDataChannel* RTCPeerConnection::createDataChannel(
    ScriptState* script_state,
    String label,
    const RTCDataChannelInit& data_channel_dict,
    ExceptionState& exception_state) {
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return nullptr;

  WebRTCDataChannelInit init;
  init.ordered = data_channel_dict.ordered();
  ExecutionContext* context = ExecutionContext::From(script_state);
  if (data_channel_dict.hasMaxRetransmitTime()) {
    UseCounter::Count(
        context,
        WebFeature::kRTCPeerConnectionCreateDataChannelMaxRetransmitTime);
    init.max_retransmit_time = data_channel_dict.maxRetransmitTime();
  }
  if (data_channel_dict.hasMaxRetransmits()) {
    UseCounter::Count(
        context, WebFeature::kRTCPeerConnectionCreateDataChannelMaxRetransmits);
    init.max_retransmits = data_channel_dict.maxRetransmits();
  }
  init.protocol = data_channel_dict.protocol();
  init.negotiated = data_channel_dict.negotiated();
  if (data_channel_dict.hasId())
    init.id = data_channel_dict.id();

  RTCDataChannel* channel = RTCDataChannel::Create(
      GetExecutionContext(), peer_handler_.get(), label, init, exception_state);
  if (exception_state.HadException())
    return nullptr;
  RTCDataChannel::ReadyState handler_state = channel->GetHandlerState();
  if (handler_state != RTCDataChannel::kReadyStateConnecting) {
    // There was an early state transition.  Don't miss it!
    channel->DidChangeReadyState(handler_state);
  }
  has_data_channels_ = true;

  return channel;
}

MediaStreamTrack* RTCPeerConnection::GetTrack(
    const WebMediaStreamTrack& web_track) const {
  return tracks_.at(static_cast<MediaStreamComponent*>(web_track));
}

HeapVector<Member<RTCRtpReceiver>>::iterator RTCPeerConnection::FindReceiver(
    const WebRTCRtpReceiver& web_receiver) {
  for (auto it = rtp_receivers_.begin(); it != rtp_receivers_.end(); ++it) {
    if ((*it)->web_receiver().Id() == web_receiver.Id())
      return it;
  }
  return rtp_receivers_.end();
}

RTCDTMFSender* RTCPeerConnection::createDTMFSender(
    MediaStreamTrack* track,
    ExceptionState& exception_state) {
  if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
    return nullptr;

  DCHECK(track);

  bool is_local_stream_track = false;
  for (const auto& local_stream : local_streams_) {
    if (local_stream->getTracks().Contains(track)) {
      is_local_stream_track = true;
      break;
    }
  }
  if (!is_local_stream_track) {
    exception_state.ThrowDOMException(
        kSyntaxError, "No local stream is available for the track provided.");
    return nullptr;
  }

  RTCDTMFSender* dtmf_sender = RTCDTMFSender::Create(
      GetExecutionContext(), peer_handler_.get(), track, exception_state);
  if (exception_state.HadException())
    return nullptr;
  return dtmf_sender;
}

void RTCPeerConnection::close() {
  if (signaling_state_ == RTCPeerConnection::kSignalingStateClosed)
    return;

  CloseInternal();
}

void RTCPeerConnection::OnStreamAddTrack(MediaStream* stream,
                                         MediaStreamTrack* track) {
  DCHECK(track);
  DCHECK(track->Component());
  // Insert if not already present.
  tracks_.insert(track->Component(), track);
}

void RTCPeerConnection::OnStreamRemoveTrack(MediaStream* stream,
                                            MediaStreamTrack* track) {
  // Don't remove |track| from |tracks_|, it may be referenced by another
  // component. |tracks_| uses weak members and will automatically have |track|
  // removed if destroyed.
}

void RTCPeerConnection::NegotiationNeeded() {
  DCHECK(!closed_);
  ScheduleDispatchEvent(Event::Create(EventTypeNames::negotiationneeded));
}

void RTCPeerConnection::DidGenerateICECandidate(
    scoped_refptr<WebRTCICECandidate> web_candidate) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());
  DCHECK(web_candidate);
  RTCIceCandidate* ice_candidate =
      RTCIceCandidate::Create(std::move(web_candidate));
  ScheduleDispatchEvent(
      RTCPeerConnectionIceEvent::Create(false, false, ice_candidate));
}

void RTCPeerConnection::DidChangeSignalingState(SignalingState new_state) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());
  ChangeSignalingState(new_state);
}

void RTCPeerConnection::DidChangeICEGatheringState(
    ICEGatheringState new_state) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());
  ChangeIceGatheringState(new_state);
}

void RTCPeerConnection::DidChangeICEConnectionState(
    ICEConnectionState new_state) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());
  ChangeIceConnectionState(new_state);
}

void RTCPeerConnection::DidAddRemoteTrack(
    std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());
  if (signaling_state_ == kSignalingStateClosed)
    return;
  HeapVector<Member<MediaStream>> streams;
  WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
  streams.ReserveCapacity(web_streams.size());
  for (const WebMediaStream& web_stream : web_streams) {
    MediaStream* stream = getRemoteStream(web_stream);
    if (!stream) {
      // This is a new stream that we need to create.
      // Get or create audio tracks.
      WebVector<WebMediaStreamTrack> audio_web_tracks;
      web_stream.AudioTracks(audio_web_tracks);
      MediaStreamTrackVector audio_tracks;
      audio_tracks.ReserveCapacity(audio_web_tracks.size());
      for (const WebMediaStreamTrack& audio_web_track : audio_web_tracks) {
        MediaStreamTrack* audio_track = tracks_.at(audio_web_track);
        if (!audio_track) {
          audio_track =
              MediaStreamTrack::Create(GetExecutionContext(), audio_web_track);
          tracks_.insert(audio_track->Component(), audio_track);
        }
        audio_tracks.push_back(audio_track);
      }
      // Get or create video tracks.
      WebVector<WebMediaStreamTrack> video_web_tracks;
      web_stream.VideoTracks(video_web_tracks);
      MediaStreamTrackVector video_tracks;
      video_tracks.ReserveCapacity(video_web_tracks.size());
      for (const WebMediaStreamTrack& video_web_track : video_web_tracks) {
        MediaStreamTrack* video_track = tracks_.at(video_web_track);
        if (!video_track) {
          video_track =
              MediaStreamTrack::Create(GetExecutionContext(), video_web_track);
          tracks_.insert(video_track->Component(), video_track);
        }
        video_tracks.push_back(video_track);
      }
      // Create stream with tracks.
      stream = MediaStream::Create(GetExecutionContext(), web_stream,
                                   audio_tracks, video_tracks);
      stream->RegisterObserver(this);
      ScheduleDispatchEvent(
          MediaStreamEvent::Create(EventTypeNames::addstream, stream));
    } else {
      // The stream already exists. Because the blink stream is wired up to
      // reflect when web tracks are added to the corresponding web stream, the
      // receiver's track will already have a blink track created for it and
      // added to the blink stream. Find it and add it to |tracks_| so that the
      // RTCPeerConnection knows of its existence.
      // TODO(hbos): This wiring is problematic since it assumes the blink track
      // should always be created. If the track already exists (on some other
      // stream or receiver) we will end up with multiple blink tracks for the
      // same component. When a web track is added to the web stream, we need to
      // check if a blink track already exists for it by querying the
      // RTCPeerConnection. https://crbug.com/769743
      MediaStreamTrack* receiver_track = nullptr;
      for (const auto& track : stream->getTracks()) {
        if (track->Component() == web_rtp_receiver->Track()) {
          receiver_track = track;
          break;
        }
      }
      DCHECK(receiver_track);
      tracks_.insert(receiver_track->Component(), receiver_track);
    }
    streams.push_back(stream);
  }
  DCHECK(FindReceiver(*web_rtp_receiver) == rtp_receivers_.end());
  MediaStreamTrack* track = GetTrack(web_rtp_receiver->Track());
  DCHECK(track);
  RTCRtpReceiver* rtp_receiver =
      new RTCRtpReceiver(std::move(web_rtp_receiver), track, streams);
  rtp_receivers_.push_back(rtp_receiver);
  ScheduleDispatchEvent(
      new RTCTrackEvent(rtp_receiver, rtp_receiver->track(), streams));
}

void RTCPeerConnection::DidRemoveRemoteTrack(
    std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());

  WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
  auto it = FindReceiver(*web_rtp_receiver);
  DCHECK(it != rtp_receivers_.end());
  RTCRtpReceiver* rtp_receiver = *it;
  MediaStreamTrack* track = rtp_receiver->track();
  rtp_receivers_.erase(it);

  // End streams no longer in use and fire "removestream" events. This behavior
  // is no longer in the spec.
  for (const WebMediaStream& web_stream : web_streams) {
    MediaStreamDescriptor* stream_descriptor = web_stream;
    DCHECK(stream_descriptor->Client());
    MediaStream* stream =
        static_cast<MediaStream*>(stream_descriptor->Client());

    // The track should already have been removed from the stream thanks to
    // wiring listening to the webrtc layer stream. This should make sure the
    // "removetrack" event fires.
    DCHECK(!stream->getTracks().Contains(track));

    // Was this the last usage of the stream? Remove from remote streams.
    if (!getRemoteStreamUsageCount(web_stream)) {
      // TODO(hbos): The stream should already have ended by being empty, no
      // need for |StreamEnded|.
      stream->StreamEnded();
      stream->UnregisterObserver(this);
      ScheduleDispatchEvent(
          MediaStreamEvent::Create(EventTypeNames::removestream, stream));
    }
  }

  // Mute track and fire "onmute" if not already muted.
  track->Component()->Source()->SetReadyState(
      MediaStreamSource::kReadyStateMuted);
}

void RTCPeerConnection::DidAddRemoteDataChannel(
    WebRTCDataChannelHandler* handler) {
  DCHECK(!closed_);
  DCHECK(GetExecutionContext()->IsContextThread());

  if (signaling_state_ == kSignalingStateClosed)
    return;

  RTCDataChannel* channel =
      RTCDataChannel::Create(GetExecutionContext(), base::WrapUnique(handler));
  ScheduleDispatchEvent(RTCDataChannelEvent::Create(EventTypeNames::datachannel,
                                                    false, false, channel));
  has_data_channels_ = true;
}

void RTCPeerConnection::ReleasePeerConnectionHandler() {
  if (stopped_)
    return;

  stopped_ = true;
  ice_connection_state_ = kICEConnectionStateClosed;
  signaling_state_ = kSignalingStateClosed;

  dispatch_scheduled_event_runner_->Stop();

  peer_handler_.reset();

  connection_handle_for_scheduler_.reset();
}

void RTCPeerConnection::ClosePeerConnection() {
  DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
  CloseInternal();
}

const AtomicString& RTCPeerConnection::InterfaceName() const {
  return EventTargetNames::RTCPeerConnection;
}

ExecutionContext* RTCPeerConnection::GetExecutionContext() const {
  return PausableObject::GetExecutionContext();
}

void RTCPeerConnection::Pause() {
  dispatch_scheduled_event_runner_->Pause();
}

void RTCPeerConnection::Unpause() {
  dispatch_scheduled_event_runner_->Unpause();
}

void RTCPeerConnection::ContextDestroyed(ExecutionContext*) {
  ReleasePeerConnectionHandler();
}

void RTCPeerConnection::ChangeSignalingState(SignalingState signaling_state) {
  if (signaling_state_ != kSignalingStateClosed) {
    signaling_state_ = signaling_state;
    ScheduleDispatchEvent(Event::Create(EventTypeNames::signalingstatechange));
  }
}

void RTCPeerConnection::ChangeIceGatheringState(
    ICEGatheringState ice_gathering_state) {
  if (ice_connection_state_ != kICEConnectionStateClosed) {
    ScheduleDispatchEvent(
        Event::Create(EventTypeNames::icegatheringstatechange),
        WTF::Bind(&RTCPeerConnection::SetIceGatheringState,
                  WrapPersistent(this), ice_gathering_state));
    if (ice_gathering_state == kICEGatheringStateComplete) {
      // If ICE gathering is completed, generate a null ICE candidate, to
      // signal end of candidates.
      ScheduleDispatchEvent(
          RTCPeerConnectionIceEvent::Create(false, false, nullptr));
    }
  }
}

bool RTCPeerConnection::SetIceGatheringState(
    ICEGatheringState ice_gathering_state) {
  if (ice_connection_state_ != kICEConnectionStateClosed &&
      ice_gathering_state_ != ice_gathering_state) {
    ice_gathering_state_ = ice_gathering_state;
    return true;
  }
  return false;
}

void RTCPeerConnection::ChangeIceConnectionState(
    ICEConnectionState ice_connection_state) {
  if (ice_connection_state_ != kICEConnectionStateClosed) {
    ScheduleDispatchEvent(
        Event::Create(EventTypeNames::iceconnectionstatechange),
        WTF::Bind(&RTCPeerConnection::SetIceConnectionState,
                  WrapPersistent(this), ice_connection_state));
  }
}

bool RTCPeerConnection::SetIceConnectionState(
    ICEConnectionState ice_connection_state) {
  if (ice_connection_state_ != kICEConnectionStateClosed &&
      ice_connection_state_ != ice_connection_state) {
    ice_connection_state_ = ice_connection_state;
    if (ice_connection_state_ == kICEConnectionStateConnected)
      RecordRapporMetrics();

    return true;
  }
  return false;
}

void RTCPeerConnection::CloseInternal() {
  DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
  peer_handler_->Stop();
  closed_ = true;

  ChangeIceConnectionState(kICEConnectionStateClosed);
  ChangeSignalingState(kSignalingStateClosed);
  Document* document = ToDocument(GetExecutionContext());
  HostsUsingFeatures::CountAnyWorld(
      *document, HostsUsingFeatures::Feature::kRTCPeerConnectionUsed);

  connection_handle_for_scheduler_.reset();
}

void RTCPeerConnection::ScheduleDispatchEvent(Event* event) {
  ScheduleDispatchEvent(event, BoolFunction());
}

void RTCPeerConnection::ScheduleDispatchEvent(Event* event,
                                              BoolFunction setup_function) {
  scheduled_events_.push_back(
      new EventWrapper(event, std::move(setup_function)));

  dispatch_scheduled_event_runner_->RunAsync();
}

void RTCPeerConnection::DispatchScheduledEvent() {
  if (stopped_)
    return;

  HeapVector<Member<EventWrapper>> events;
  events.swap(scheduled_events_);

  HeapVector<Member<EventWrapper>>::iterator it = events.begin();
  for (; it != events.end(); ++it) {
    if ((*it)->Setup()) {
      DispatchEvent((*it)->event_.Release());
    }
  }

  events.clear();
}

void RTCPeerConnection::RecordRapporMetrics() {
  Document* document = ToDocument(GetExecutionContext());
  for (const auto& component : tracks_.Keys()) {
    switch (component->Source()->GetType()) {
      case MediaStreamSource::kTypeAudio:
        HostsUsingFeatures::CountAnyWorld(
            *document, HostsUsingFeatures::Feature::kRTCPeerConnectionAudio);
        break;
      case MediaStreamSource::kTypeVideo:
        HostsUsingFeatures::CountAnyWorld(
            *document, HostsUsingFeatures::Feature::kRTCPeerConnectionVideo);
        break;
      default:
        NOTREACHED();
    }
  }

  if (has_data_channels_)
    HostsUsingFeatures::CountAnyWorld(
        *document, HostsUsingFeatures::Feature::kRTCPeerConnectionDataChannel);
}

void RTCPeerConnection::Trace(blink::Visitor* visitor) {
  visitor->Trace(local_streams_);
  visitor->Trace(tracks_);
  visitor->Trace(rtp_senders_);
  visitor->Trace(rtp_receivers_);
  visitor->Trace(dispatch_scheduled_event_runner_);
  visitor->Trace(scheduled_events_);
  EventTargetWithInlineData::Trace(visitor);
  PausableObject::Trace(visitor);
  MediaStreamObserver::Trace(visitor);
}

int RTCPeerConnection::PeerConnectionCount() {
  return InstanceCounters::CounterValue(
      InstanceCounters::kRTCPeerConnectionCounter);
}

int RTCPeerConnection::PeerConnectionCountLimit() {
  return kMaxPeerConnections;
}

}  // namespace blink
