Shaka Player Embedded
media_key_session.cc
Go to the documentation of this file.
1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #include <cmath>
18 #include <vector>
19 
20 #include "src/js/js_error.h"
21 
22 namespace shaka {
23 namespace js {
24 namespace eme {
25 
27  std::shared_ptr<ImplementationFactory> factory,
28  std::shared_ptr<Implementation> implementation)
29  : closed(Promise::PendingPromise()),
30  mutex_("MediaKeySession"),
31  factory_(factory),
32  implementation_(implementation),
33  type_(type),
34  closed_promise_(closed, /* has_value */ false) {
35  AddListenerField(EventType::KeyStatusesChange, &on_key_statuses_change);
36  AddListenerField(EventType::Message, &on_message);
37 }
38 
39 // \cond Doxygen_Skip
40 MediaKeySession::~MediaKeySession() {}
41 // \endcond Doxygen_Skip
42 
43 
45  EventTarget::Trace(tracer);
46  tracer->Trace(&closed);
47 }
48 
49 std::string MediaKeySession::SessionId() const {
50  std::unique_lock<Mutex> lock(mutex_);
51  return session_id_;
52 }
53 
55  const std::string session_id = SessionId();
56  if (session_id.empty())
57  return NAN;
58 
59  int64_t expiration;
60  if (!implementation_->GetExpiration(session_id, &expiration)) {
61  return JsError::TypeError("Error getting the expiration");
62  }
63  return expiration < 0 ? NAN : expiration;
64 }
65 
67  std::vector<KeyStatusInfo> statuses;
68  const std::string session_id = SessionId();
69  if (!session_id.empty() &&
70  !implementation_->GetKeyStatuses(session_id, &statuses)) {
71  return JsError::TypeError("Error getting the key statuses");
72  }
73 
74  LocalVar<JsMap> ret(CreateMap());
75  for (auto& status : statuses) {
76  LocalVar<JsValue> key(
77  ToJsValue(ByteBuffer(status.key_id.data(), status.key_id.size())));
78  LocalVar<JsValue> value(ToJsValue(status.status));
79  SetMapValue(ret, key, value);
80  }
81  return RawToJsValue(ret);
82 }
83 
85  ByteBuffer init_data) {
86  if (!SessionId().empty()) {
88  InvalidStateError, "Session already initialized"));
89  }
90  if (init_data.size() == 0) {
91  return Promise::Rejected(
92  JsError::TypeError("Initialization data is empty"));
93  }
94  if (!factory_->SupportsInitDataType(init_data_type)) {
97  "CDM implementation doesn't support this initialization data type"));
98  }
99 
100  auto cb = [this](const std::string& session_id) {
101  std::unique_lock<Mutex> lock(mutex_);
102  CHECK(session_id_.empty()) << "Cannot call set_session_id() twice.";
103  session_id_ = session_id;
104  };
106  implementation_->CreateSessionAndGenerateRequest(
107  EmePromise(ret, /* has_value */ false), cb, type_, init_data_type,
108  Data(&init_data));
109  return ret;
110 }
111 
112 Promise MediaKeySession::Load(const std::string& session_id) {
113  if (!SessionId().empty()) {
115  InvalidStateError, "Session already initialized"));
116  }
117  if (session_id.empty()) {
118  return Promise::Rejected(JsError::TypeError("Empty session ID"));
119  }
120  if (type_ != MediaKeySessionType::PersistentLicense) {
122  "Cannot load a persistent license in a temporary session"));
123  }
124 
126  implementation_->Load(session_id, EmePromise(ret, /* has_value */ true));
127  // TODO: This shouldn't be changed if the Promise is rejected.
128  session_id_ = session_id;
129  return ret;
130 }
131 
133  const std::string session_id = SessionId();
134  if (session_id.empty()) {
135  return Promise::Rejected(
136  JsError::DOMException(InvalidStateError, "Session not initialized"));
137  }
138  if (response.size() == 0) {
139  return Promise::Rejected(JsError::TypeError("Empty response data"));
140  }
141 
143  implementation_->Update(session_id, EmePromise(ret, /* has_value */ false),
144  Data(&response));
145  return ret;
146 }
147 
149  const std::string session_id = SessionId();
150  if (session_id.empty()) {
151  return Promise::Resolved();
152  }
153 
154  implementation_->Close(session_id, closed_promise_);
155  return closed;
156 }
157 
159  const std::string session_id = SessionId();
160  if (session_id.empty()) {
161  return Promise::Rejected(
162  JsError::DOMException(InvalidStateError, "Session not initialized"));
163  }
164 
166  implementation_->Remove(session_id, EmePromise(ret, /* has_value */ false));
167  return ret;
168 }
169 
170 
172  AddListenerField(EventType::KeyStatusesChange,
174  AddListenerField(EventType::Message, &MediaKeySession::on_message);
175 
176  AddGenericProperty("sessionId", &MediaKeySession::SessionId);
177  AddReadOnlyProperty("closed", &MediaKeySession::closed);
178 
179  AddGenericProperty("expiration", &MediaKeySession::GetExpiration);
180  AddGenericProperty("keyStatuses", &MediaKeySession::GetKeyStatuses);
181 
182  AddMemberFunction("generateRequest", &MediaKeySession::GenerateRequest);
183  AddMemberFunction("load", &MediaKeySession::Load);
184  AddMemberFunction("update", &MediaKeySession::Update);
185  AddMemberFunction("close", &MediaKeySession::Close);
186  AddMemberFunction("remove", &MediaKeySession::Remove);
187 }
188 
189 } // namespace eme
190 } // namespace js
191 } // namespace shaka
Promise GenerateRequest(MediaKeyInitDataType init_data_type, ByteBuffer init_data)
void Trace(memory::HeapTracer *tracer) const override
ReturnVal< JsValue > ToJsValue(T &&source)
Definition: convert_js.h:381
ExceptionOr< ReturnVal< JsValue > > GetKeyStatuses() const
ReturnVal< JsValue > RawToJsValue(Handle< T > source)
Definition: js_wrappers.h:405
ExceptionCode type
void Trace(const Traceable *ptr)
Definition: heap_tracer.cc:43
MediaKeySession(MediaKeySessionType type, std::shared_ptr< ImplementationFactory > factory, std::shared_ptr< Implementation > implementation)
size_t size() const
Definition: byte_buffer.h:55
Promise Load(const std::string &session_id)
static Promise Rejected(const js::JsError &error)
Definition: promise.h:77
ReturnVal< JsMap > CreateMap()
Definition: js_wrappers.cc:300
void SetMapValue(Handle< JsMap > map, Handle< JsValue > key, Handle< JsValue > value)
Definition: js_wrappers.cc:304
static Promise PendingPromise()
Definition: promise.h:54
static JsError TypeError(const std::string &message)
Definition: js_error.cc:81
static JsError DOMException(ExceptionCode code)
Definition: js_error.cc:115
static Promise Resolved()
Definition: promise.h:64
void AddListenerField(EventType type, Listener *on_field)
Definition: event_target.h:138
ExceptionOr< double > GetExpiration() const
Promise Update(ByteBuffer response)