1// Copyright 2013 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. 4 5#include "content/renderer/media/webcontentdecryptionmodulesession_impl.h" 6 7#include "base/bind.h" 8#include "base/callback_helpers.h" 9#include "base/logging.h" 10#include "base/strings/string_util.h" 11#include "base/strings/utf_string_conversions.h" 12#include "content/renderer/media/cdm_session_adapter.h" 13#include "media/base/cdm_promise.h" 14#include "third_party/WebKit/public/platform/WebURL.h" 15 16namespace content { 17 18WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( 19 Client* client, 20 const scoped_refptr<CdmSessionAdapter>& adapter) 21 : adapter_(adapter), 22 client_(client), 23 is_closed_(false), 24 weak_ptr_factory_(this) { 25} 26 27WebContentDecryptionModuleSessionImpl:: 28 ~WebContentDecryptionModuleSessionImpl() { 29 if (!web_session_id_.empty()) 30 adapter_->RemoveSession(web_session_id_); 31} 32 33blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { 34 return blink::WebString::fromUTF8(web_session_id_); 35} 36 37void WebContentDecryptionModuleSessionImpl::initializeNewSession( 38 const blink::WebString& init_data_type, 39 const uint8* init_data, 40 size_t init_data_length) { 41 // TODO(ddorwin): Guard against this in supported types check and remove this. 42 // Chromium only supports ASCII MIME types. 43 if (!base::IsStringASCII(init_data_type)) { 44 NOTREACHED(); 45 OnSessionError(media::MediaKeys::NOT_SUPPORTED_ERROR, 46 0, 47 "The initialization data type " + init_data_type.utf8() + 48 " is not supported by the key system."); 49 return; 50 } 51 52 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type); 53 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos) 54 << "init_data_type '" << init_data_type_as_ascii 55 << "' may be a MIME type"; 56 57 scoped_ptr<media::NewSessionCdmPromise> promise( 58 new media::NewSessionCdmPromise( 59 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated, 60 weak_ptr_factory_.GetWeakPtr()), 61 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError, 62 weak_ptr_factory_.GetWeakPtr()))); 63 adapter_->InitializeNewSession(init_data_type_as_ascii, 64 init_data, 65 init_data_length, 66 media::MediaKeys::TEMPORARY_SESSION, 67 promise.Pass()); 68} 69 70void WebContentDecryptionModuleSessionImpl::update(const uint8* response, 71 size_t response_length) { 72 DCHECK(response); 73 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( 74 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionReady, 75 weak_ptr_factory_.GetWeakPtr()), 76 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError, 77 weak_ptr_factory_.GetWeakPtr()))); 78 adapter_->UpdateSession( 79 web_session_id_, response, response_length, promise.Pass()); 80} 81 82void WebContentDecryptionModuleSessionImpl::release() { 83 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( 84 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed, 85 weak_ptr_factory_.GetWeakPtr()), 86 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError, 87 weak_ptr_factory_.GetWeakPtr()))); 88 adapter_->ReleaseSession(web_session_id_, promise.Pass()); 89} 90 91void WebContentDecryptionModuleSessionImpl::OnSessionMessage( 92 const std::vector<uint8>& message, 93 const GURL& destination_url) { 94 client_->message( 95 message.empty() ? NULL : &message[0], message.size(), destination_url); 96} 97 98void WebContentDecryptionModuleSessionImpl::OnSessionReady() { 99 client_->ready(); 100} 101 102void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { 103 if (!is_closed_) { 104 is_closed_ = true; 105 client_->close(); 106 } 107} 108 109void WebContentDecryptionModuleSessionImpl::OnSessionError( 110 media::MediaKeys::Exception exception_code, 111 uint32 system_code, 112 const std::string& error_message) { 113 // Convert |exception_code| back to MediaKeyErrorCode if possible. 114 // TODO(jrummell): Update this conversion when promises flow 115 // back into blink:: (as blink:: will have its own error definition). 116 switch (exception_code) { 117 case media::MediaKeys::CLIENT_ERROR: 118 client_->error(Client::MediaKeyErrorCodeClient, system_code); 119 break; 120 default: 121 // This will include all other CDM4 errors and any error generated 122 // by CDM5 or later. 123 client_->error(Client::MediaKeyErrorCodeUnknown, system_code); 124 break; 125 } 126} 127 128void WebContentDecryptionModuleSessionImpl::SessionCreated( 129 const std::string& web_session_id) { 130 DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set."; 131 web_session_id_ = web_session_id; 132 adapter_->RegisterSession(web_session_id_, weak_ptr_factory_.GetWeakPtr()); 133} 134 135} // namespace content 136