summaryrefslogtreecommitdiff
path: root/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
blob: 50ebcd09f857dd0308bae9126c5a5b3c244f66cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/cdm_session_adapter.h"
#include "media/base/cdm_promise.h"
#include "third_party/WebKit/public/platform/WebURL.h"

namespace content {

WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
    Client* client,
    const scoped_refptr<CdmSessionAdapter>& adapter)
    : adapter_(adapter),
      client_(client),
      is_closed_(false),
      weak_ptr_factory_(this) {
}

WebContentDecryptionModuleSessionImpl::
    ~WebContentDecryptionModuleSessionImpl() {
  if (!web_session_id_.empty())
    adapter_->RemoveSession(web_session_id_);
}

blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
  return blink::WebString::fromUTF8(web_session_id_);
}

void WebContentDecryptionModuleSessionImpl::initializeNewSession(
    const blink::WebString& init_data_type,
    const uint8* init_data,
    size_t init_data_length) {
  // TODO(ddorwin): Guard against this in supported types check and remove this.
  // Chromium only supports ASCII MIME types.
  if (!base::IsStringASCII(init_data_type)) {
    NOTREACHED();
    OnSessionError(media::MediaKeys::NOT_SUPPORTED_ERROR,
                   0,
                   "The initialization data type " + init_data_type.utf8() +
                       " is not supported by the key system.");
    return;
  }

  std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
  DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
      << "init_data_type '" << init_data_type_as_ascii
      << "' may be a MIME type";

  scoped_ptr<media::NewSessionCdmPromise> promise(
      new media::NewSessionCdmPromise(
          base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated,
                     weak_ptr_factory_.GetWeakPtr()),
          base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                     weak_ptr_factory_.GetWeakPtr())));
  adapter_->InitializeNewSession(init_data_type_as_ascii,
                                 init_data,
                                 init_data_length,
                                 media::MediaKeys::TEMPORARY_SESSION,
                                 promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
                                                   size_t response_length) {
  DCHECK(response);
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionReady,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                 weak_ptr_factory_.GetWeakPtr())));
  adapter_->UpdateSession(
      web_session_id_, response, response_length, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::release() {
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                 weak_ptr_factory_.GetWeakPtr())));
  adapter_->ReleaseSession(web_session_id_, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
    const std::vector<uint8>& message,
    const GURL& destination_url) {
  client_->message(
      message.empty() ? NULL : &message[0], message.size(), destination_url);
}

void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
  client_->ready();
}

void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
  if (!is_closed_) {
    is_closed_ = true;
    client_->close();
  }
}

void WebContentDecryptionModuleSessionImpl::OnSessionError(
    media::MediaKeys::Exception exception_code,
    uint32 system_code,
    const std::string& error_message) {
  // Convert |exception_code| back to MediaKeyErrorCode if possible.
  // TODO(jrummell): Update this conversion when promises flow
  // back into blink:: (as blink:: will have its own error definition).
  switch (exception_code) {
    case media::MediaKeys::CLIENT_ERROR:
      client_->error(Client::MediaKeyErrorCodeClient, system_code);
      break;
    default:
      // This will include all other CDM4 errors and any error generated
      // by CDM5 or later.
      client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
      break;
  }
}

void WebContentDecryptionModuleSessionImpl::SessionCreated(
    const std::string& web_session_id) {
  DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
  web_session_id_ = web_session_id;
  adapter_->RegisterSession(web_session_id_, weak_ptr_factory_.GetWeakPtr());
}

}  // namespace content