// 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/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 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,
                     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) {}

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;
}

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
