1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/crypto/proxy_media_keys.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <vector>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/basictypes.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/stl_util.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/crypto/key_systems.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/crypto/renderer_cdm_manager.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/cdm_promise.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace content {
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_ptr<ProxyMediaKeys> ProxyMediaKeys::Create(
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& key_system,
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const GURL& security_origin,
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RendererCdmManager* manager,
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const media::SessionMessageCB& session_message_cb,
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const media::SessionReadyCB& session_ready_cb,
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const media::SessionClosedCB& session_closed_cb,
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const media::SessionErrorCB& session_error_cb,
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const media::SessionKeysChangeCB& session_keys_change_cb,
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(manager);
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(jrummell): Add support for SessionKeysChangeCB and
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // SessionExpirationUpdateCB.
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<ProxyMediaKeys> proxy_media_keys(
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new ProxyMediaKeys(manager,
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                         session_message_cb,
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                         session_ready_cb,
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                         session_closed_cb,
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                         session_error_cb));
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  proxy_media_keys->InitializeCdm(key_system, security_origin);
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return proxy_media_keys.Pass();
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ProxyMediaKeys::~ProxyMediaKeys() {
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  manager_->DestroyCdm(cdm_id_);
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  manager_->UnregisterMediaKeys(cdm_id_);
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Reject any outstanding promises.
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (PromiseMap::iterator it = session_id_to_promise_map_.begin();
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != session_id_to_promise_map_.end();
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       ++it) {
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    it->second->reject(
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        media::MediaKeys::NOT_SUPPORTED_ERROR, 0, "The operation was aborted.");
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_id_to_promise_map_.clear();
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyMediaKeys::SetServerCertificate(
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const uint8* certificate_data,
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int certificate_data_length,
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<media::SimpleCdmPromise> promise) {
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::CreateSession(
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& init_data_type,
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const uint8* init_data,
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int init_data_length,
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SessionType session_type,
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<media::NewSessionCdmPromise> promise) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(xhwang): Move these checks up to blink and DCHECK here.
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // See http://crbug.com/342510
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CdmHostMsg_CreateSession_ContentType create_session_content_type;
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (init_data_type == "cenc") {
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    create_session_content_type = CREATE_SESSION_TYPE_MP4;
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (init_data_type == "webm") {
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    create_session_content_type = CREATE_SESSION_TYPE_WEBM;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(ERROR) << "Unsupported EME CreateSession content type of "
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << init_data_type;
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    promise->reject(
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        NOT_SUPPORTED_ERROR,
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        0,
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        "Unsupported EME CreateSession init data type of " + init_data_type);
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint32 session_id = CreateSessionId();
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SavePromise(session_id, promise.PassAs<media::CdmPromise>());
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  manager_->CreateSession(
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cdm_id_,
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      session_id,
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      create_session_content_type,
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::vector<uint8>(init_data, init_data + init_data_length));
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::LoadSession(
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& web_session_id,
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<media::NewSessionCdmPromise> promise) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(xhwang): Check key system and platform support for LoadSession in
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // blink and add NOTREACHED() here.
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading.";
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported.");
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::UpdateSession(
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& web_session_id,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const uint8* response,
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int response_length,
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<media::SimpleCdmPromise> promise) {
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint32 session_id = LookupSessionId(web_session_id);
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!session_id) {
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist.");
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SavePromise(session_id, promise.PassAs<media::CdmPromise>());
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  manager_->UpdateSession(
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cdm_id_,
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      session_id,
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::vector<uint8>(response, response + response_length));
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyMediaKeys::CloseSession(const std::string& web_session_id,
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  scoped_ptr<media::SimpleCdmPromise> promise) {
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint32 session_id = LookupSessionId(web_session_id);
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!session_id) {
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist.");
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SavePromise(session_id, promise.PassAs<media::CdmPromise>());
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  manager_->ReleaseSession(cdm_id_, session_id);
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyMediaKeys::RemoveSession(
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& web_session_id,
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<media::SimpleCdmPromise> promise) {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyMediaKeys::GetUsableKeyIds(const std::string& web_session_id,
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     scoped_ptr<media::KeyIdsPromise> promise) {
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProxyMediaKeys::OnSessionCreated(uint32 session_id,
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      const std::string& web_session_id) {
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AssignWebSessionId(session_id, web_session_id);
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<media::CdmPromise> promise = TakePromise(session_id);
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (promise) {
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    media::NewSessionCdmPromise* session_promise(
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        static_cast<media::NewSessionCdmPromise*>(promise.get()));
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    session_promise->resolve(web_session_id);
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProxyMediaKeys::OnSessionMessage(uint32 session_id,
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      const std::vector<uint8>& message,
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      const GURL& destination_url) {
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_message_cb_.Run(
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LookupWebSessionId(session_id), message, destination_url);
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProxyMediaKeys::OnSessionReady(uint32 session_id) {
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<media::CdmPromise> promise = TakePromise(session_id);
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (promise) {
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    media::SimpleCdmPromise* simple_promise(
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        static_cast<media::SimpleCdmPromise*>(promise.get()));
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    simple_promise->resolve();
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Still needed for keyadded.
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string web_session_id = LookupWebSessionId(session_id);
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    session_ready_cb_.Run(web_session_id);
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProxyMediaKeys::OnSessionClosed(uint32 session_id) {
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string web_session_id = LookupWebSessionId(session_id);
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DropWebSessionId(web_session_id);
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<media::CdmPromise> promise = TakePromise(session_id);
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (promise) {
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    media::SimpleCdmPromise* simple_promise(
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        static_cast<media::SimpleCdmPromise*>(promise.get()));
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    simple_promise->resolve();
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // It is possible for the CDM to close a session independent of a
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Release() request.
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    session_closed_cb_.Run(web_session_id);
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProxyMediaKeys::OnSessionError(uint32 session_id,
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    media::MediaKeys::KeyError error_code,
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    uint32 system_code) {
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string web_session_id = LookupWebSessionId(session_id);
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  media::MediaKeys::Exception exception_code;
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  switch (error_code) {
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case media::MediaKeys::kClientError:
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      exception_code = media::MediaKeys::CLIENT_ERROR;
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case media::MediaKeys::kOutputError:
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      exception_code = media::MediaKeys::OUTPUT_ERROR;
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case media::MediaKeys::kUnknownError:
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    default:
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      exception_code = media::MediaKeys::UNKNOWN_ERROR;
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<media::CdmPromise> promise = TakePromise(session_id);
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (promise) {
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    promise->reject(exception_code, system_code, std::string());
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Errors generally happen in response to a request, but it is possible
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // for something bad to happen in the CDM and it needs to tell the client.
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_error_cb_.Run(
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      web_session_id, exception_code, system_code, std::string());
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochint ProxyMediaKeys::GetCdmId() const {
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return cdm_id_;
223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochProxyMediaKeys::ProxyMediaKeys(
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RendererCdmManager* manager,
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const media::SessionMessageCB& session_message_cb,
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const media::SessionReadyCB& session_ready_cb,
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const media::SessionClosedCB& session_closed_cb,
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const media::SessionErrorCB& session_error_cb)
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : manager_(manager),
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      session_message_cb_(session_message_cb),
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      session_ready_cb_(session_ready_cb),
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      session_closed_cb_(session_closed_cb),
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      session_error_cb_(session_error_cb),
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      next_session_id_(1) {
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cdm_id_ = manager->RegisterMediaKeys(this);
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ProxyMediaKeys::InitializeCdm(const std::string& key_system,
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                   const GURL& security_origin) {
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  manager_->InitializeCdm(cdm_id_, this, key_system, security_origin);
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)uint32_t ProxyMediaKeys::CreateSessionId() {
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return next_session_id_++;
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::AssignWebSessionId(uint32_t session_id,
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        const std::string& web_session_id) {
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!ContainsKey(web_session_to_session_id_map_, web_session_id));
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(session_id);
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  web_session_to_session_id_map_.insert(
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      std::make_pair(web_session_id, session_id));
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)uint32_t ProxyMediaKeys::LookupSessionId(
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& web_session_id) const {
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SessionIdMap::const_iterator it =
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      web_session_to_session_id_map_.find(web_session_id);
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (it != web_session_to_session_id_map_.end()) ? it->second : 0;
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string ProxyMediaKeys::LookupWebSessionId(uint32_t session_id) const {
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (SessionIdMap::const_iterator it = web_session_to_session_id_map_.begin();
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != web_session_to_session_id_map_.end();
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       ++it) {
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (it->second == session_id)
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return it->first;
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Possible to get an error creating a session, so no |web_session_id|
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // available.
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return std::string();
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::DropWebSessionId(const std::string& web_session_id) {
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  web_session_to_session_id_map_.erase(web_session_id);
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyMediaKeys::SavePromise(uint32_t session_id,
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 scoped_ptr<media::CdmPromise> promise) {
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Should only be one promise outstanding for any |session_id|.
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!ContainsKey(session_id_to_promise_map_, session_id));
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_id_to_promise_map_.add(session_id, promise.Pass());
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr<media::CdmPromise> ProxyMediaKeys::TakePromise(uint32_t session_id) {
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PromiseMap::iterator it = session_id_to_promise_map_.find(session_id);
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // May not be a promise associated with this session for asynchronous events.
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it == session_id_to_promise_map_.end())
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return scoped_ptr<media::CdmPromise>();
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return session_id_to_promise_map_.take_and_erase(it);
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace content
296