// 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 "cobalt/dom/captions/system_caption_settings.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/dom_settings.h"
#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 "starboard/configuration_constants.h"
#include "starboard/file.h"
#include "starboard/media.h"

using cobalt::media_session::MediaSession;

namespace cobalt {
namespace dom {
namespace {

const char kLicensesRelativePath[] = "/licenses/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, const std::string& user_agent,
    const std::string& language, scoped_refptr<MediaSession> media_session,
    scoped_refptr<cobalt::dom::captions::SystemCaptionSettings> captions,
    script::ScriptValueFactory* script_value_factory)
    : user_agent_(user_agent),
      language_(language),
      mime_types_(new MimeTypeArray()),
      plugins_(new PluginArray()),
      media_session_(media_session),
      media_devices_(
          new media_capture::MediaDevices(settings, script_value_factory)),
      system_caption_settings_(captions),
      script_value_factory_(script_value_factory) {}

const std::string& Navigator::language() const { return language_; }

base::Optional<std::string> GetFilenameForLicenses() {
  const size_t kBufferSize = kSbFileMaxPath + 1;
  std::vector<char> buffer(kBufferSize, 0);
  bool got_path = SbSystemGetPath(kSbSystemPathContentDirectory, buffer.data(),
                                  static_cast<int>(kBufferSize));
  if (!got_path) {
    SB_DLOG(ERROR) << "Cannot get content path for licenses files.";
    return base::Optional<std::string>();
  }

  return std::string(buffer.data()).append(kLicensesRelativePath);
}

const std::string Navigator::licenses() const {
  base::Optional<std::string> filename = GetFilenameForLicenses();
  if (!filename) {
    return std::string();
  }

  SbFile file = SbFileOpen(filename->c_str(), kSbFileOpenOnly | kSbFileRead,
                           nullptr, nullptr);
  if (file == kSbFileInvalid) {
    SB_DLOG(WARNING) << "Cannot open licenses file: " << *filename;
    return std::string();
  }

  SbFileInfo info;
  bool success = SbFileGetInfo(file, &info);
  if (!success) {
    SB_DLOG(WARNING) << "Cannot get information for licenses file.";
    SbFileClose(file);
    return std::string();
  }
  // SbFileReadAll expects an int for the size argument. Assume that the file
  // is smaller than 2^32.
  int file_size = static_cast<int>(info.size);

  std::unique_ptr<char[]> buffer(new char[file_size]);
  SbFileReadAll(file, buffer.get(), file_size);
  const std::string file_contents = std::string(buffer.get(), file_size);
  SbFileClose(file);

  return file_contents;
}

const std::string& Navigator::user_agent() const { return user_agent_; }

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()
    const {
  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<MediaKeySystemMediaCapability>>
Navigator::TryGetSupportedCapabilities(
    const media::CanPlayTypeHandler& can_play_type_handler,
    const std::string& key_system,
    const script::Sequence<MediaKeySystemMediaCapability>&
        requested_media_capabilities) {
  // 2. Let supported media capabilities be an empty sequence of
  //    MediaKeySystemMediaCapability dictionaries.
  script::Sequence<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 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<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<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<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<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) {
  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 DOMException(DOMException::kNotSupportedErr));
  return promise;
}

const scoped_refptr<cobalt::dom::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 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
