// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/navigator.h"

#include <memory>
#include <vector>

#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/dom/captions/system_caption_settings.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/embedded_licenses.h"  // Generated file.
#include "cobalt/dom/eme/media_key_system_access.h"
#include "cobalt/media_capture/media_devices.h"
#include "cobalt/media_session/media_session_client.h"
#include "cobalt/script/script_value_factory.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/web/navigator_base.h"
#include "cobalt/worker/service_worker_container.h"
#include "starboard/configuration_constants.h"
#include "starboard/file.h"
#include "starboard/media.h"

namespace cobalt {
namespace dom {
namespace {

const char kEmbeddedLicenses[] = "licenses_cobalt.txt";

#if !defined(COBALT_BUILD_TYPE_GOLD)

std::string ToString(const std::string& str, int indent_level);
std::string ToString(const eme::MediaKeySystemMediaCapability& capability,
                     int indent_level);
std::string ToString(const eme::MediaKeySystemConfiguration& configuration,
                     int indent_level);

std::string GetIndent(int indent_level) {
  std::string indent;
  while (indent_level > 0) {
    indent += "  ";
    --indent_level;
  }
  return indent;
}

template <typename T>
std::string ToString(const script::Sequence<T>& sequence, int indent_level) {
  std::stringstream ss;

  ss << "{\n";

  for (auto iter = sequence.begin(); iter != sequence.end(); ++iter) {
    ss << ToString(*iter, indent_level + 1) << ",\n";
  }

  ss << GetIndent(indent_level) << "}";

  return ss.str();
}

std::string ToString(const std::string& str, int indent_level) {
  return GetIndent(indent_level) + str;
}

std::string ToString(const eme::MediaKeySystemMediaCapability& capability,
                     int indent_level) {
  return GetIndent(indent_level) + '\'' + capability.content_type() + "'/'" +
         capability.encryption_scheme().value_or("(null)") + '\'';
}

std::string ToString(const eme::MediaKeySystemConfiguration& configuration,
                     int indent_level) {
  DCHECK(configuration.has_label());

  std::stringstream ss;

  ss << GetIndent(indent_level) << "label:'" << configuration.label()
     << "': {\n";
  if (configuration.has_init_data_types()) {
    ss << GetIndent(indent_level + 1) << "init_data_types: "
       << ToString(configuration.init_data_types(), indent_level + 1) << ",\n";
  }
  if (configuration.has_audio_capabilities()) {
    ss << GetIndent(indent_level + 1) << "audio_capabilities: "
       << ToString(configuration.audio_capabilities(), indent_level + 1)
       << ",\n";
  }
  if (configuration.has_video_capabilities()) {
    ss << GetIndent(indent_level + 1) << "video_capabilities: "
       << ToString(configuration.video_capabilities(), indent_level + 1)
       << ",\n";
  }
  ss << GetIndent(indent_level) << "}";

  return ss.str();
}

#endif  // !defined(COBALT_BUILD_TYPE_GOLD)

// This function is used when the underlying SbMediaCanPlayMimeAndKeySystem()
// implementation doesn't support extra attributes on |key_system|, it makes
// decision based on the key system itself.
bool IsEncryptionSchemeSupportedByDefault(
    const std::string& key_system, const std::string& encryption_scheme) {
  // 1. Playready only supports "cenc".
  if (key_system.find("playready") != key_system.npos) {
    return encryption_scheme == "cenc";
  }
  // 2. Fairplay only supports "cbcs" and "cbcs-1-9".
  if (key_system.find("fairplay") != key_system.npos) {
    return encryption_scheme == "cbcs" || encryption_scheme == "cbcs-1-9";
  }
  // 3. Widevine only supports "cenc", "cbcs" and "cbcs-1-9".
  if (key_system.find("widevine") != key_system.npos) {
    return encryption_scheme == "cenc" || encryption_scheme == "cbcs" ||
           encryption_scheme == "cbcs-1-9";
  }

  // The key system is unknown, assume only "cenc" is supported.
  return encryption_scheme == "cenc";
}

bool CanPlay(const media::CanPlayTypeHandler& can_play_type_handler,
             const std::string& content_type, const std::string& key_system) {
  auto can_play_result = can_play_type_handler.CanPlayAdaptive(
      content_type.c_str(), key_system.c_str());
  LOG_IF(INFO, can_play_result == kSbMediaSupportTypeMaybe)
      << "CanPlayAdaptive() returns \"maybe\".";
  return can_play_result == kSbMediaSupportTypeProbably ||
         can_play_result == kSbMediaSupportTypeMaybe;
}

}  // namespace

Navigator::Navigator(script::EnvironmentSettings* settings,
                     scoped_refptr<captions::SystemCaptionSettings> captions)
    : web::NavigatorBase(settings),
      mime_types_(new MimeTypeArray()),
      plugins_(new PluginArray()),
      media_devices_(
          new media_capture::MediaDevices(settings, script_value_factory())),
      system_caption_settings_(captions) {}

const std::string Navigator::licenses() const {
  GeneratedResourceMap resource_map;
  DOMEmbeddedResources::GenerateMap(resource_map);
  FileContents file_contents = resource_map[kEmbeddedLicenses];
  return std::string(reinterpret_cast<const char*>(file_contents.data),
                     file_contents.size);
}

bool Navigator::java_enabled() const { return false; }

bool Navigator::cookie_enabled() const { return false; }

scoped_refptr<media_capture::MediaDevices> Navigator::media_devices() {
  return media_devices_;
}

const scoped_refptr<MimeTypeArray>& Navigator::mime_types() const {
  return mime_types_;
}

const scoped_refptr<PluginArray>& Navigator::plugins() const {
  return plugins_;
}

const scoped_refptr<media_session::MediaSession>& Navigator::media_session() {
  if (media_session_ == nullptr) {
    media_session_ = scoped_refptr<media_session::MediaSession>(
        new media_session::MediaSession());

    if (media_player_factory_ != nullptr) {
      media_session_->EnsureMediaSessionClient();
      DCHECK(media_session_->media_session_client());
      media_session_->media_session_client()->SetMaybeFreezeCallback(
          maybe_freeze_callback_);
      media_session_->media_session_client()->SetMediaPlayerFactory(
          media_player_factory_);
    }
  }
  return media_session_;
}

// TODO: Move the following two functions to the bottom of the file, in sync
//       with the order of declaration.
// See
// https://www.w3.org/TR/encrypted-media/#get-supported-capabilities-for-audio-video-type.
base::Optional<script::Sequence<eme::MediaKeySystemMediaCapability>>
Navigator::TryGetSupportedCapabilities(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& key_system,
    const script::Sequence<eme::MediaKeySystemMediaCapability>&
        requested_media_capabilities) {
  // 2. Let supported media capabilities be an empty sequence of
  //    MediaKeySystemMediaCapability dictionaries.
  script::Sequence<eme::MediaKeySystemMediaCapability>
      supported_media_capabilities;
  // 3. For each requested media capability in requested media capabilities:
  for (std::size_t media_capability_index = 0;
       media_capability_index < requested_media_capabilities.size();
       ++media_capability_index) {
    const eme::MediaKeySystemMediaCapability& requested_media_capability =
        requested_media_capabilities.at(media_capability_index);
    // 3.1. Let content type be requested media capability's contentType member.
    const std::string& content_type = requested_media_capability.content_type();
    // 3.3. If content type is the empty string, return null.
    if (content_type.empty()) {
      return base::nullopt;
    }
    // 3.13. If the user agent and [CDM] implementation definitely support
    //       playback of encrypted media data for the combination of container,
    //       media types [...]:
    if (CanPlayWithCapability(can_play_type_handler, key_system,
                              requested_media_capability)) {
      // 3.13.1. Add requested media capability to supported media capabilities.
      supported_media_capabilities.push_back(requested_media_capability);
    }
  }
  // 4. If supported media capabilities is empty, return null.
  if (supported_media_capabilities.empty()) {
    return base::nullopt;
  }
  // 5. Return supported media capabilities.
  return supported_media_capabilities;
}

// Technically, a user agent is supposed to implement "3.1.1.1 Get Supported
// Configuration" which requests the user consent until it's given. But since
// Cobalt never interacts with the user directly, we'll assume that the consent
// is always given and go straight to "3.1.1.2 Get Supported Configuration and
// Consent". See
// https://www.w3.org/TR/encrypted-media/#get-supported-configuration-and-consent.
base::Optional<eme::MediaKeySystemConfiguration>
Navigator::TryGetSupportedConfiguration(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& key_system,
    const eme::MediaKeySystemConfiguration& candidate_configuration) {
  // 1. Let accumulated configuration be a new MediaKeySystemConfiguration
  //    dictionary.
  eme::MediaKeySystemConfiguration accumulated_configuration;

  // 2. Set the label member of accumulated configuration to equal the label
  //    member of candidate configuration.
  accumulated_configuration.set_label(candidate_configuration.label());

  // For now, copy initialization data types into accumulated configuration.
  //
  // TODO: Implement step 3 after introducing a Starboard API for detecting
  //       supported initialization data type.
  // TODO: Checking has_init_data_types() won't be needed once Cobalt supports
  //       default values for IDL sequences.
  accumulated_configuration.set_init_data_types(
      candidate_configuration.has_init_data_types()
          ? candidate_configuration.init_data_types()
          : script::Sequence<std::string>());

  // TODO: Reject distinctive identifiers, persistent state, and persistent
  //       sessions.

  // 15. If the videoCapabilities and audioCapabilities members in candidate
  //     configuration are both empty, return NotSupported.
  //
  // TODO: Checking has_video_capabilities() and has_audio_capabilities() won't
  //       be needed once Cobalt supports default values for IDL sequences.
  if ((!candidate_configuration.has_video_capabilities() ||
       candidate_configuration.video_capabilities().empty()) &&
      (!candidate_configuration.has_audio_capabilities() ||
       candidate_configuration.audio_capabilities().empty())) {
    return base::nullopt;
  }

  // 16. If the videoCapabilities member in candidate configuration is
  //     non-empty:
  if (candidate_configuration.has_video_capabilities() &&
      !candidate_configuration.video_capabilities().empty()) {
    // 16.1. Let video capabilities be the result of executing the "Get
    //       Supported Capabilities for Audio/Video Type" algorithm.
    base::Optional<script::Sequence<eme::MediaKeySystemMediaCapability>>
        maybe_video_capabilities = TryGetSupportedCapabilities(
            can_play_type_handler, key_system,
            candidate_configuration.video_capabilities());
    // 16.2. If video capabilities is null, return NotSupported.
    if (!maybe_video_capabilities) {
      return base::nullopt;
    }
    // 16.3. Set the videoCapabilities member of accumulated configuration to
    //       video capabilities.
    accumulated_configuration.set_video_capabilities(*maybe_video_capabilities);
  } else {
    // Otherwise: set the videoCapabilities member of accumulated configuration
    // to an empty sequence.
    accumulated_configuration.set_video_capabilities(
        script::Sequence<eme::MediaKeySystemMediaCapability>());
  }

  // 17. If the audioCapabilities member in candidate configuration is
  //     non-empty:
  if (candidate_configuration.has_audio_capabilities() &&
      !candidate_configuration.audio_capabilities().empty()) {
    // 17.1. Let audio capabilities be the result of executing the "Get
    //       Supported Capabilities for Audio/Video Type" algorithm.
    base::Optional<script::Sequence<eme::MediaKeySystemMediaCapability>>
        maybe_audio_capabilities = TryGetSupportedCapabilities(
            can_play_type_handler, key_system,
            candidate_configuration.audio_capabilities());
    // 17.2. If audio capabilities is null, return NotSupported.
    if (!maybe_audio_capabilities) {
      return base::nullopt;
    }
    // 17.3. Set the audioCapabilities member of accumulated configuration to
    //       audio capabilities.
    accumulated_configuration.set_audio_capabilities(*maybe_audio_capabilities);
  } else {
    // Otherwise: set the audioCapabilities member of accumulated configuration
    // to an empty sequence.
    accumulated_configuration.set_audio_capabilities(
        script::Sequence<eme::MediaKeySystemMediaCapability>());
  }

  // 23. Return accumulated configuration.
  return accumulated_configuration;
}

// See
// https://www.w3.org/TR/encrypted-media/#dom-navigator-requestmediakeysystemaccess.
script::Handle<Navigator::InterfacePromise>
Navigator::RequestMediaKeySystemAccess(
    script::EnvironmentSettings* settings, const std::string& key_system,
    const script::Sequence<eme::MediaKeySystemConfiguration>&
        supported_configurations) {
  TRACE_EVENT1("cobalt::dom", "Navigator::RequestMediaKeySystemAccess()",
               "key_system", key_system);
  DCHECK(settings);
  DOMSettings* dom_settings =
      base::polymorphic_downcast<DOMSettings*>(settings);
  DCHECK(dom_settings->can_play_type_handler());
  script::Handle<InterfacePromise> promise =
      script_value_factory()
          ->CreateInterfacePromise<scoped_refptr<eme::MediaKeySystemAccess>>();

#if !defined(COBALT_BUILD_TYPE_GOLD)
  LOG(INFO) << "Navigator.RequestMediaKeySystemAccess() called with '"
            << key_system << "', and\n"
            << ToString(supported_configurations, 0);
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)

  // 1. If |keySystem| is the empty string, return a promise rejected
  //    with a newly created TypeError.
  // 2. If |supportedConfigurations| is empty, return a promise rejected
  //    with a newly created TypeError.
  if (key_system.empty() || supported_configurations.empty()) {
    promise->Reject(script::kTypeError);
    return promise;
  }

  // 6.3. For each value in |supportedConfigurations|:
  for (std::size_t configuration_index = 0;
       configuration_index < supported_configurations.size();
       ++configuration_index) {
    // 6.3.3. If supported configuration is not NotSupported:
    base::Optional<eme::MediaKeySystemConfiguration>
        maybe_supported_configuration = TryGetSupportedConfiguration(
            *dom_settings->can_play_type_handler(), key_system,
            supported_configurations.at(configuration_index));
    if (maybe_supported_configuration) {
      // 6.3.3.1. Let access be a new MediaKeySystemAccess object.
      scoped_refptr<eme::MediaKeySystemAccess> media_key_system_access(
          new eme::MediaKeySystemAccess(key_system,
                                        *maybe_supported_configuration,
                                        script_value_factory()));
#if !defined(COBALT_BUILD_TYPE_GOLD)
      LOG(INFO) << "Navigator.RequestMediaKeySystemAccess() resolved with '"
                << media_key_system_access->key_system() << "', and\n"
                << ToString(media_key_system_access->GetConfiguration(), 0);
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
      // 6.3.3.2. Resolve promise.
      promise->Resolve(media_key_system_access);
      return promise;
    }
  }

  // 6.4. Reject promise with a NotSupportedError.
  promise->Reject(new web::DOMException(web::DOMException::kNotSupportedErr));
  return promise;
}

const scoped_refptr<captions::SystemCaptionSettings>&
Navigator::system_caption_settings() const {
  return system_caption_settings_;
}

void Navigator::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(mime_types_);
  tracer->Trace(plugins_);
  tracer->Trace(media_session_);
  tracer->Trace(media_devices_);
  tracer->Trace(system_caption_settings_);
}

bool Navigator::CanPlayWithCapability(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& key_system,
    const eme::MediaKeySystemMediaCapability& media_capability) {
  const std::string& content_type = media_capability.content_type();

  // There is no encryption scheme specified, check directly.
  if (!media_capability.encryption_scheme().has_value()) {
    if (CanPlay(can_play_type_handler, content_type, key_system)) {
      LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
                << ", " << key_system << ") -> supported";
      return true;
    }
    LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
              << ", " << key_system << ") -> not supported";
    return false;
  }

  if (!key_system_with_attributes_supported_.has_value()) {
    if (!CanPlay(can_play_type_handler, content_type, key_system)) {
      // If the check on the basic key system fails, we don't even bother to
      // check if it supports key system with attributes.
      LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
                << ", " << key_system << ") -> not supported";
      return false;
    }
    auto key_system_with_invalid_attribute =
        std::string(key_system) + "; invalid_attributes=\"value\"";
    // If an implementation supports attributes, it should ignore unknown
    // attributes and return true, as the key system has been verified to be
    // supported above.
    key_system_with_attributes_supported_ = CanPlay(
        can_play_type_handler, content_type, key_system_with_invalid_attribute);
    if (key_system_with_attributes_supported_.value()) {
      LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() will use key"
                << " system with attributes.";
    } else {
      LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() won't use key"
                << " system with attributes.";
    }
  }

  DCHECK(key_system_with_attributes_supported_.has_value());

  // As a key system with attributes support is optional, and the logic to
  // determine whether the encryptionScheme is supported can be quite different
  // depending on whether this is supported, we encapsulate the logic into two
  // different functions.
  if (key_system_with_attributes_supported_.value()) {
    return CanPlayWithAttributes(can_play_type_handler, content_type,
                                 key_system,
                                 media_capability.encryption_scheme().value());
  }

  return CanPlayWithoutAttributes(can_play_type_handler, content_type,
                                  key_system,
                                  media_capability.encryption_scheme().value());
}

bool Navigator::CanPlayWithoutAttributes(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& content_type, const std::string& key_system,
    const std::string& encryption_scheme) {
  DCHECK(key_system_with_attributes_supported_.has_value());
  DCHECK(!key_system_with_attributes_supported_.value());

  if (!IsEncryptionSchemeSupportedByDefault(key_system, encryption_scheme)) {
    LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() rejects "
              << key_system << " because encryptionScheme \""
              << encryption_scheme << "\" is not supported.";
    return false;
  }

  if (CanPlay(can_play_type_handler, content_type, key_system)) {
    LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
              << ", " << key_system << ") with encryptionScheme \""
              << encryption_scheme << "\" -> supported";
    return true;
  }

  LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type << ", "
            << key_system << ") with encryptionScheme \"" << encryption_scheme
            << "\" -> not supported";
  return false;
}

bool Navigator::CanPlayWithAttributes(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& content_type, const std::string& key_system,
    const std::string& encryption_scheme) {
  DCHECK(key_system_with_attributes_supported_.has_value());
  DCHECK(key_system_with_attributes_supported_.value());

  auto key_system_with_attributes =
      key_system + "; encryptionscheme=\"" + encryption_scheme + '"';

  if (CanPlay(can_play_type_handler, content_type,
              key_system_with_attributes)) {
    LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
              << ", " << key_system << ") with encryptionScheme \""
              << encryption_scheme << "\" -> supported";
    return true;
  }

  LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type << ", "
            << key_system << ") with encryptionScheme \"" << encryption_scheme
            << "\" -> not supported";
  return false;
}

}  // namespace dom
}  // namespace cobalt
