blob: b7c94d6e12692bdbe200d316825fb3478ad52685 [file] [log] [blame]
// Copyright 2017 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/eme/media_keys.h"
#include "base/bind.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/eme/eme_helpers.h"
#include "cobalt/dom/eme/media_key_session.h"
namespace cobalt {
namespace dom {
namespace eme {
MediaKeys::MediaKeys(const scoped_refptr<media::DrmSystem>& drm_system,
script::ScriptValueFactory* script_value_factory)
: script_value_factory_(script_value_factory), drm_system_(drm_system) {
SB_DCHECK(drm_system_->is_valid()) << "DrmSystem provided on initialization is invalid.";
}
// See https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession.
scoped_refptr<MediaKeySession> MediaKeys::CreateSession(
MediaKeySessionType session_type, script::ExceptionState* exception_state) {
// 1. If this object's supported session types value does not contain
// sessionType, throw a NotSupportedError.
if (session_type != kMediaKeySessionTypeTemporary) {
DOMException::Raise(DOMException::kNotSupportedErr, exception_state);
return NULL;
}
// 3. Let session be a new MediaKeySession object.
//
// |MediaKeys| are passed to |MediaKeySession| as weak pointer because the
// order of destruction is not guaranteed due to JavaScript memory management.
scoped_refptr<MediaKeySession> session(new MediaKeySession(
drm_system_, script_value_factory_,
base::Bind(&MediaKeys::OnSessionClosed, AsWeakPtr())));
open_sessions_.push_back(session);
return session;
}
MediaKeys::BoolPromiseHandle MediaKeys::SetServerCertificate(
const BufferSource& server_certificate) {
BoolPromiseHandle promise = script_value_factory_->CreateBasicPromise<bool>();
// 1. If the Key System implementation represented by this object's cdm
// implementation value does not support server certificates, return a
// promise resolved with false.
if (!drm_system_->IsServerCertificateUpdatable()) {
promise->Resolve(false);
return promise;
}
// 2. If serverCertificate is an empty array, return a promise rejected with a
// newly created TypeError.
const uint8* server_certificate_buffer;
int server_certificate_buffer_size = 0;
GetBufferAndSize(server_certificate, &server_certificate_buffer,
&server_certificate_buffer_size);
if (server_certificate_buffer_size == 0) {
promise->Reject(script::kTypeError);
return promise;
}
// 3. Let certificate be a copy of the contents of the serverCertificate
// parameter.
// 4. Let promise be a new promise.
// 5. Run the following steps in parallel:
// 5.1 Let sanitized certificate be a validated and/or sanitized version of
// certificate.
// 5.2 Use this object's cdm instance to process sanitized certificate.
drm_system_->UpdateServerCertificate(
server_certificate_buffer, server_certificate_buffer_size,
base::Bind(&MediaKeys::OnServerCertificateUpdated, base::AsWeakPtr(this),
base::Owned(new BoolPromiseValue::Reference(this, promise))));
// 5.3 and 5.4 are pending processing in OnServerCertificateUpdated().
// 6. Return promise.
return promise;
}
void MediaKeys::OnSessionClosed(MediaKeySession* session) {
// Erase-remove idiom, see
// https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom.
open_sessions_.erase(
std::remove(open_sessions_.begin(), open_sessions_.end(), session),
open_sessions_.end());
}
void MediaKeys::OnServerCertificateUpdated(
BoolPromiseValue::Reference* promise_reference, SbDrmStatus status,
const std::string& error_message) {
// 5.3 If the preceding step failed, resolve promise with a new DOMException
// whose name is the appropriate error name.
if (status != kSbDrmStatusSuccess) {
RejectPromise(promise_reference, status, error_message);
return;
}
// 5.4 Resolve promise with true.
promise_reference->value().Resolve(true);
}
void MediaKeys::TraceMembers(script::Tracer* tracer) {
tracer->TraceItems(open_sessions_);
}
MediaKeys::~MediaKeys() {}
} // namespace eme
} // namespace dom
} // namespace cobalt