Prevent UAF of RenderFrames from GuestViewContainer
[chromium-blink-merge.git] / media / blink / webencryptedmediaclient_impl.cc
blobaf7b7f487a99cc44cf5254257835e1d4c8fbdfe9
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 "webencryptedmediaclient_impl.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "media/base/key_systems.h"
11 #include "net/base/mime_util.h"
12 #include "third_party/WebKit/public/platform/WebEncryptedMediaRequest.h"
13 #include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h"
14 #include "third_party/WebKit/public/platform/WebString.h"
15 #include "third_party/WebKit/public/platform/WebVector.h"
16 #include "webcontentdecryptionmoduleaccess_impl.h"
18 namespace media {
20 static bool IsSupportedContentType(
21 const std::string& key_system,
22 const std::string& mime_type,
23 const std::string& codecs) {
24 // Per RFC 6838, "Both top-level type and subtype names are case-insensitive."
25 // TODO(sandersd): Check that |container| matches the capability:
26 // - audioCapabilitys: audio/mp4 or audio/webm.
27 // - videoCapabilitys: video/mp4 or video/webm.
28 // http://crbug.com/429781.
29 std::string container = base::StringToLowerASCII(mime_type);
31 // TODO(sandersd): Strict checking for codecs. http://crbug.com/374751.
32 bool strip_codec_suffixes = !net::IsStrictMediaMimeType(container);
33 std::vector<std::string> codec_vector;
34 net::ParseCodecString(codecs, &codec_vector, strip_codec_suffixes);
35 return IsSupportedKeySystemWithMediaMimeType(container, codec_vector,
36 key_system);
39 static bool GetSupportedConfiguration(
40 const std::string& key_system,
41 const blink::WebMediaKeySystemConfiguration& candidate,
42 const blink::WebSecurityOrigin& security_origin,
43 blink::WebMediaKeySystemConfiguration* accumulated_configuration) {
44 if (!candidate.initDataTypes.isEmpty()) {
45 std::vector<blink::WebString> init_data_types;
47 for (size_t i = 0; i < candidate.initDataTypes.size(); i++) {
48 const blink::WebString& init_data_type = candidate.initDataTypes[i];
49 if (init_data_type.isEmpty())
50 return false;
51 if (base::IsStringASCII(init_data_type) &&
52 IsSupportedKeySystemWithInitDataType(
53 key_system, base::UTF16ToASCII(init_data_type))) {
54 init_data_types.push_back(init_data_type);
58 if (init_data_types.empty())
59 return false;
61 accumulated_configuration->initDataTypes = init_data_types;
64 // TODO(sandersd): Implement distinctiveIdentifier and persistentState checks.
65 if (candidate.distinctiveIdentifier !=
66 blink::WebMediaKeySystemConfiguration::Requirement::Optional ||
67 candidate.persistentState !=
68 blink::WebMediaKeySystemConfiguration::Requirement::Optional) {
69 return false;
72 if (!candidate.audioCapabilities.isEmpty()) {
73 std::vector<blink::WebMediaKeySystemMediaCapability> audio_capabilities;
75 for (size_t i = 0; i < candidate.audioCapabilities.size(); i++) {
76 const blink::WebMediaKeySystemMediaCapability& capabilities =
77 candidate.audioCapabilities[i];
78 if (capabilities.mimeType.isEmpty())
79 return false;
80 if (!base::IsStringASCII(capabilities.mimeType) ||
81 !base::IsStringASCII(capabilities.codecs) ||
82 !IsSupportedContentType(
83 key_system, base::UTF16ToASCII(capabilities.mimeType),
84 base::UTF16ToASCII(capabilities.codecs))) {
85 continue;
87 // TODO(sandersd): Support robustness.
88 if (!capabilities.robustness.isEmpty())
89 continue;
90 audio_capabilities.push_back(capabilities);
93 if (audio_capabilities.empty())
94 return false;
96 accumulated_configuration->audioCapabilities = audio_capabilities;
99 if (!candidate.videoCapabilities.isEmpty()) {
100 std::vector<blink::WebMediaKeySystemMediaCapability> video_capabilities;
102 for (size_t i = 0; i < candidate.videoCapabilities.size(); i++) {
103 const blink::WebMediaKeySystemMediaCapability& capabilities =
104 candidate.videoCapabilities[i];
105 if (capabilities.mimeType.isEmpty())
106 return false;
107 if (!base::IsStringASCII(capabilities.mimeType) ||
108 !base::IsStringASCII(capabilities.codecs) ||
109 !IsSupportedContentType(
110 key_system, base::UTF16ToASCII(capabilities.mimeType),
111 base::UTF16ToASCII(capabilities.codecs))) {
112 continue;
114 // TODO(sandersd): Support robustness.
115 if (!capabilities.robustness.isEmpty())
116 continue;
117 video_capabilities.push_back(capabilities);
120 if (video_capabilities.empty())
121 return false;
123 accumulated_configuration->videoCapabilities = video_capabilities;
126 // TODO(sandersd): Prompt for distinctive identifiers and/or persistent state
127 // if required. Make sure that future checks are silent.
128 // http://crbug.com/446263.
130 return true;
133 WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl(
134 scoped_ptr<CdmFactory> cdm_factory)
135 : cdm_factory_(cdm_factory.Pass()) {
138 WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() {
141 void WebEncryptedMediaClientImpl::requestMediaKeySystemAccess(
142 blink::WebEncryptedMediaRequest request) {
143 // TODO(jrummell): This should be asynchronous.
145 // Continued from requestMediaKeySystemAccess(), step 7, from
146 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess
148 // 7.1 If keySystem is not one of the Key Systems supported by the user
149 // agent, reject promise with with a new DOMException whose name is
150 // NotSupportedError. String comparison is case-sensitive.
151 if (!base::IsStringASCII(request.keySystem())) {
152 request.requestNotSupported("Only ASCII keySystems are supported");
153 return;
156 std::string key_system = base::UTF16ToASCII(request.keySystem());
157 if (!IsConcreteSupportedKeySystem(key_system)) {
158 request.requestNotSupported("Unsupported keySystem");
159 return;
162 // 7.2 Let implementation be the implementation of keySystem.
163 // 7.3 Follow the steps for the first matching condition from the following
164 // list:
165 // - If supportedConfigurations was not provided, run the Is Key System
166 // Supported? algorithm and if successful, resolve promise with access
167 // and abort these steps.
168 // TODO(sandersd): Remove pending the resolution of
169 // https://github.com/w3c/encrypted-media/issues/1.
170 const blink::WebVector<blink::WebMediaKeySystemConfiguration>&
171 configurations = request.supportedConfigurations();
172 if (configurations.isEmpty()) {
173 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create(
174 request.keySystem(), request.securityOrigin(), cdm_factory_.get()));
175 return;
178 // - Otherwise, for each value in supportedConfigurations, run the
179 // GetSuppored Configuration algorithm and if successful, resolve
180 // promise with access and abort these steps.
181 for (size_t i = 0; i < configurations.size(); i++) {
182 const blink::WebMediaKeySystemConfiguration& candidate = configurations[i];
183 blink::WebMediaKeySystemConfiguration accumulated_configuration;
184 if (GetSupportedConfiguration(key_system, candidate,
185 request.securityOrigin(),
186 &accumulated_configuration)) {
187 // TODO(sandersd): Pass the accumulated configuration along.
188 // http://crbug.com/447059.
189 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create(
190 request.keySystem(), request.securityOrigin(), cdm_factory_.get()));
191 return;
195 // 7.4 Reject promise with a new DOMException whose name is NotSupportedError.
196 request.requestNotSupported(
197 "None of the requested configurations were supported.");
200 } // namespace media