1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/media/cdm/browser_cdm_cast.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "media/base/cdm_key_information.h"
12 #include "media/base/cdm_promise.h"
13 #include "media/cdm/player_tracker_impl.h"
15 namespace chromecast
{
20 // media::CdmPromiseTemplate implementation that wraps a promise so as to
21 // allow passing to other threads.
22 template <typename
... T
>
23 class CdmPromiseInternal
: public ::media::CdmPromiseTemplate
<T
...> {
25 CdmPromiseInternal(scoped_ptr
<::media::CdmPromiseTemplate
<T
...>> promise
)
26 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
27 promise_(promise
.Pass()) {
30 ~CdmPromiseInternal() final
{
31 // Promise must be resolved or rejected before destruction.
35 // CdmPromiseTemplate<> implementation.
36 void resolve(const T
&... result
) final
;
38 void reject(::media::MediaKeys::Exception exception
,
40 const std::string
& error_message
) final
{
42 task_runner_
->PostTask(
44 base::Bind(&::media::CdmPromiseTemplate
<T
...>::reject
,
45 base::Owned(promise_
.release()),
46 exception
, system_code
, error_message
));
50 using ::media::CdmPromiseTemplate
<T
...>::MarkPromiseSettled
;
52 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
53 scoped_ptr
<::media::CdmPromiseTemplate
<T
...>> promise_
;
56 template <typename
... T
>
57 void CdmPromiseInternal
<T
...>::resolve(const T
&... result
) {
59 task_runner_
->PostTask(
61 base::Bind(&::media::CdmPromiseTemplate
<T
...>::resolve
,
62 base::Owned(promise_
.release()),
66 template <typename
... T
>
67 scoped_ptr
<CdmPromiseInternal
<T
...>> BindPromiseToCurrentLoop(
68 scoped_ptr
<::media::CdmPromiseTemplate
<T
...>> promise
) {
69 return make_scoped_ptr(new CdmPromiseInternal
<T
...>(promise
.Pass()));
74 BrowserCdmCast::BrowserCdmCast() {
75 thread_checker_
.DetachFromThread();
78 BrowserCdmCast::~BrowserCdmCast() {
79 DCHECK(thread_checker_
.CalledOnValidThread());
80 DCHECK(player_tracker_impl_
.get());
81 player_tracker_impl_
->NotifyCdmUnset();
84 void BrowserCdmCast::Initialize(
85 const ::media::SessionMessageCB
& session_message_cb
,
86 const ::media::SessionClosedCB
& session_closed_cb
,
87 const ::media::LegacySessionErrorCB
& legacy_session_error_cb
,
88 const ::media::SessionKeysChangeCB
& session_keys_change_cb
,
89 const ::media::SessionExpirationUpdateCB
& session_expiration_update_cb
) {
90 DCHECK(thread_checker_
.CalledOnValidThread());
92 player_tracker_impl_
.reset(new ::media::PlayerTrackerImpl
);
94 session_message_cb_
= session_message_cb
;
95 session_closed_cb_
= session_closed_cb
;
96 legacy_session_error_cb_
= legacy_session_error_cb
;
97 session_keys_change_cb_
= session_keys_change_cb
;
98 session_expiration_update_cb_
= session_expiration_update_cb
;
100 InitializeInternal();
103 int BrowserCdmCast::RegisterPlayer(const base::Closure
& new_key_cb
,
104 const base::Closure
& cdm_unset_cb
) {
105 DCHECK(thread_checker_
.CalledOnValidThread());
106 return player_tracker_impl_
->RegisterPlayer(new_key_cb
, cdm_unset_cb
);
109 void BrowserCdmCast::UnregisterPlayer(int registration_id
) {
110 DCHECK(thread_checker_
.CalledOnValidThread());
111 player_tracker_impl_
->UnregisterPlayer(registration_id
);
114 ::media::CdmContext
* BrowserCdmCast::GetCdmContext() {
119 void BrowserCdmCast::OnSessionMessage(
120 const std::string
& session_id
,
121 const std::vector
<uint8_t>& message
,
122 const GURL
& destination_url
,
123 ::media::MediaKeys::MessageType message_type
) {
124 session_message_cb_
.Run(session_id
,
130 void BrowserCdmCast::OnSessionClosed(const std::string
& session_id
) {
131 session_closed_cb_
.Run(session_id
);
134 void BrowserCdmCast::OnSessionKeysChange(
135 const std::string
& session_id
,
136 const ::media::KeyIdAndKeyPairs
& keys
) {
137 ::media::CdmKeysInfo cdm_keys_info
;
138 for (const std::pair
<std::string
, std::string
>& key
: keys
) {
139 scoped_ptr
< ::media::CdmKeyInformation
> cdm_key_information(
140 new ::media::CdmKeyInformation());
141 cdm_key_information
->key_id
.assign(key
.first
.begin(), key
.first
.end());
142 cdm_keys_info
.push_back(cdm_key_information
.release());
144 session_keys_change_cb_
.Run(session_id
, true, cdm_keys_info
.Pass());
146 player_tracker_impl_
->NotifyNewKey();
149 // A macro runs current member function on |task_runner_| thread.
150 #define FORWARD_ON_CDM_THREAD(param_fn, ...) \
151 task_runner_->PostTask( \
153 base::Bind(&BrowserCdmCast::param_fn, \
154 base::Unretained(browser_cdm_cast_.get()), ##__VA_ARGS__))
156 BrowserCdmCastUi::BrowserCdmCastUi(
157 scoped_ptr
<BrowserCdmCast
> browser_cdm_cast
,
158 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
)
159 : browser_cdm_cast_(browser_cdm_cast
.Pass()), task_runner_(task_runner
) {
162 BrowserCdmCastUi::~BrowserCdmCastUi() {
163 DCHECK(thread_checker_
.CalledOnValidThread());
164 task_runner_
->DeleteSoon(FROM_HERE
, browser_cdm_cast_
.release());
167 int BrowserCdmCastUi::RegisterPlayer(const base::Closure
& new_key_cb
,
168 const base::Closure
& cdm_unset_cb
) {
169 NOTREACHED() << "RegisterPlayer should be called on BrowserCdmCast";
173 void BrowserCdmCastUi::UnregisterPlayer(int registration_id
) {
174 NOTREACHED() << "UnregisterPlayer should be called on BrowserCdmCast";
177 BrowserCdmCast
* BrowserCdmCastUi::browser_cdm_cast() const {
178 DCHECK(thread_checker_
.CalledOnValidThread());
179 return browser_cdm_cast_
.get();
182 void BrowserCdmCastUi::SetServerCertificate(
183 const std::vector
<uint8_t>& certificate
,
184 scoped_ptr
<::media::SimpleCdmPromise
> promise
) {
185 DCHECK(thread_checker_
.CalledOnValidThread());
186 FORWARD_ON_CDM_THREAD(
187 SetServerCertificate
,
189 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
192 void BrowserCdmCastUi::CreateSessionAndGenerateRequest(
193 ::media::MediaKeys::SessionType session_type
,
194 ::media::EmeInitDataType init_data_type
,
195 const std::vector
<uint8_t>& init_data
,
196 scoped_ptr
<::media::NewSessionCdmPromise
> promise
) {
197 DCHECK(thread_checker_
.CalledOnValidThread());
198 FORWARD_ON_CDM_THREAD(
199 CreateSessionAndGenerateRequest
,
203 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
206 void BrowserCdmCastUi::LoadSession(
207 ::media::MediaKeys::SessionType session_type
,
208 const std::string
& session_id
,
209 scoped_ptr
<::media::NewSessionCdmPromise
> promise
) {
210 DCHECK(thread_checker_
.CalledOnValidThread());
211 FORWARD_ON_CDM_THREAD(
212 LoadSession
, session_type
, session_id
,
213 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
216 void BrowserCdmCastUi::UpdateSession(
217 const std::string
& session_id
,
218 const std::vector
<uint8_t>& response
,
219 scoped_ptr
<::media::SimpleCdmPromise
> promise
) {
220 DCHECK(thread_checker_
.CalledOnValidThread());
221 FORWARD_ON_CDM_THREAD(
225 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
228 void BrowserCdmCastUi::CloseSession(
229 const std::string
& session_id
,
230 scoped_ptr
<::media::SimpleCdmPromise
> promise
) {
231 DCHECK(thread_checker_
.CalledOnValidThread());
232 FORWARD_ON_CDM_THREAD(CloseSession
, session_id
,
233 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
236 void BrowserCdmCastUi::RemoveSession(
237 const std::string
& session_id
,
238 scoped_ptr
<::media::SimpleCdmPromise
> promise
) {
239 DCHECK(thread_checker_
.CalledOnValidThread());
240 FORWARD_ON_CDM_THREAD(RemoveSession
, session_id
,
241 base::Passed(BindPromiseToCurrentLoop(promise
.Pass())));
244 ::media::CdmContext
* BrowserCdmCastUi::GetCdmContext() {
249 // A default empty implementation for subclasses that don't need to provide
250 // any key system specific initialization.
251 void BrowserCdmCast::InitializeInternal() {
255 } // namespace chromecast