OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "key_system_config_selector.h" | 5 #include "key_system_config_selector.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 return EmeConfigRule::PERSISTENCE_REQUIRED; | 124 return EmeConfigRule::PERSISTENCE_REQUIRED; |
125 } | 125 } |
126 | 126 |
127 } // namespace | 127 } // namespace |
128 | 128 |
129 struct KeySystemConfigSelector::SelectionRequest { | 129 struct KeySystemConfigSelector::SelectionRequest { |
130 std::string key_system; | 130 std::string key_system; |
131 blink::WebVector<blink::WebMediaKeySystemConfiguration> | 131 blink::WebVector<blink::WebMediaKeySystemConfiguration> |
132 candidate_configurations; | 132 candidate_configurations; |
133 blink::WebSecurityOrigin security_origin; | 133 blink::WebSecurityOrigin security_origin; |
134 base::Callback<void(const blink::WebMediaKeySystemConfiguration&, bool)> | 134 base::Callback<void(const blink::WebMediaKeySystemConfiguration&)> |
135 succeeded_cb; | 135 succeeded_cb; |
136 base::Callback<void(const blink::WebString&)> not_supported_cb; | 136 base::Callback<void(const blink::WebString&)> not_supported_cb; |
137 bool was_permission_requested = false; | 137 bool was_permission_requested = false; |
138 bool is_permission_granted = false; | 138 bool is_permission_granted = false; |
139 bool are_secure_codecs_supported = false; | |
140 }; | 139 }; |
141 | 140 |
142 // Accumulates configuration rules to determine if a feature (additional | 141 // Accumulates configuration rules to determine if a feature (additional |
143 // configuration rule) can be added to an accumulated configuration. | 142 // configuration rule) can be added to an accumulated configuration. |
144 class KeySystemConfigSelector::ConfigState { | 143 class KeySystemConfigSelector::ConfigState { |
145 public: | 144 public: |
146 ConfigState(bool was_permission_requested, bool is_permission_granted) | 145 ConfigState(bool was_permission_requested, bool is_permission_granted) |
147 : was_permission_requested_(was_permission_requested), | 146 : was_permission_requested_(was_permission_requested), |
148 is_permission_granted_(is_permission_granted) {} | 147 is_permission_granted_(is_permission_granted) {} |
149 | 148 |
150 bool IsPermissionGranted() const { return is_permission_granted_; } | 149 bool IsPermissionGranted() const { return is_permission_granted_; } |
151 | 150 |
152 // Permission is possible if it has not been denied. | 151 // Permission is possible if it has not been denied. |
153 bool IsPermissionPossible() const { | 152 bool IsPermissionPossible() const { |
154 return is_permission_granted_ || !was_permission_requested_; | 153 return is_permission_granted_ || !was_permission_requested_; |
155 } | 154 } |
156 | 155 |
157 bool IsIdentifierRequired() const { return is_identifier_required_; } | 156 bool IsIdentifierRequired() const { return is_identifier_required_; } |
158 | 157 |
159 bool IsIdentifierRecommended() const { return is_identifier_recommended_; } | 158 bool IsIdentifierRecommended() const { return is_identifier_recommended_; } |
160 | 159 |
161 bool AreSecureCodecsRequired() const { | |
162 return are_secure_codecs_required_; | |
163 } | |
164 | |
165 // Checks whether a rule is compatible with all previously added rules. | 160 // Checks whether a rule is compatible with all previously added rules. |
166 bool IsRuleSupported(EmeConfigRule rule) const { | 161 bool IsRuleSupported(EmeConfigRule rule) const { |
167 switch (rule) { | 162 switch (rule) { |
168 case EmeConfigRule::NOT_SUPPORTED: | 163 case EmeConfigRule::NOT_SUPPORTED: |
169 return false; | 164 return false; |
170 case EmeConfigRule::IDENTIFIER_NOT_ALLOWED: | 165 case EmeConfigRule::IDENTIFIER_NOT_ALLOWED: |
171 return !is_identifier_required_; | 166 return !is_identifier_required_; |
172 case EmeConfigRule::IDENTIFIER_REQUIRED: | 167 case EmeConfigRule::IDENTIFIER_REQUIRED: |
173 // TODO(sandersd): Confirm if we should be refusing these rules when | 168 // TODO(sandersd): Confirm if we should be refusing these rules when |
174 // permission has been denied (as the spec currently says). | 169 // permission has been denied (as the spec currently says). |
175 return !is_identifier_not_allowed_ && IsPermissionPossible(); | 170 return !is_identifier_not_allowed_ && IsPermissionPossible(); |
176 case EmeConfigRule::IDENTIFIER_RECOMMENDED: | 171 case EmeConfigRule::IDENTIFIER_RECOMMENDED: |
177 return true; | 172 return true; |
178 case EmeConfigRule::PERSISTENCE_NOT_ALLOWED: | 173 case EmeConfigRule::PERSISTENCE_NOT_ALLOWED: |
179 return !is_persistence_required_; | 174 return !is_persistence_required_; |
180 case EmeConfigRule::PERSISTENCE_REQUIRED: | 175 case EmeConfigRule::PERSISTENCE_REQUIRED: |
181 return !is_persistence_not_allowed_; | 176 return !is_persistence_not_allowed_; |
182 case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED: | 177 case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED: |
183 return (!is_identifier_not_allowed_ && IsPermissionPossible() && | 178 return (!is_identifier_not_allowed_ && IsPermissionPossible() && |
184 !is_persistence_not_allowed_); | 179 !is_persistence_not_allowed_); |
| 180 #if defined(OS_ANDROID) |
185 case EmeConfigRule::SECURE_CODECS_NOT_ALLOWED: | 181 case EmeConfigRule::SECURE_CODECS_NOT_ALLOWED: |
186 return !are_secure_codecs_required_; | 182 return !are_secure_codecs_required_; |
187 case EmeConfigRule::SECURE_CODECS_REQUIRED: | 183 case EmeConfigRule::SECURE_CODECS_REQUIRED: |
188 return !are_secure_codecs_not_allowed_; | 184 return !are_secure_codecs_not_allowed_; |
| 185 #endif // defined(OS_ANDROID) |
189 case EmeConfigRule::SUPPORTED: | 186 case EmeConfigRule::SUPPORTED: |
190 return true; | 187 return true; |
191 } | 188 } |
192 NOTREACHED(); | 189 NOTREACHED(); |
193 return false; | 190 return false; |
194 } | 191 } |
195 | 192 |
196 // Add a rule to the accumulated configuration state. | 193 // Add a rule to the accumulated configuration state. |
197 void AddRule(EmeConfigRule rule) { | 194 void AddRule(EmeConfigRule rule) { |
198 DCHECK(IsRuleSupported(rule)); | 195 DCHECK(IsRuleSupported(rule)); |
(...skipping 13 matching lines...) Expand all Loading... |
212 case EmeConfigRule::PERSISTENCE_NOT_ALLOWED: | 209 case EmeConfigRule::PERSISTENCE_NOT_ALLOWED: |
213 is_persistence_not_allowed_ = true; | 210 is_persistence_not_allowed_ = true; |
214 return; | 211 return; |
215 case EmeConfigRule::PERSISTENCE_REQUIRED: | 212 case EmeConfigRule::PERSISTENCE_REQUIRED: |
216 is_persistence_required_ = true; | 213 is_persistence_required_ = true; |
217 return; | 214 return; |
218 case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED: | 215 case EmeConfigRule::IDENTIFIER_AND_PERSISTENCE_REQUIRED: |
219 is_identifier_required_ = true; | 216 is_identifier_required_ = true; |
220 is_persistence_required_ = true; | 217 is_persistence_required_ = true; |
221 return; | 218 return; |
| 219 #if defined(OS_ANDROID) |
222 case EmeConfigRule::SECURE_CODECS_NOT_ALLOWED: | 220 case EmeConfigRule::SECURE_CODECS_NOT_ALLOWED: |
223 are_secure_codecs_not_allowed_ = true; | 221 are_secure_codecs_not_allowed_ = true; |
224 return; | 222 return; |
225 case EmeConfigRule::SECURE_CODECS_REQUIRED: | 223 case EmeConfigRule::SECURE_CODECS_REQUIRED: |
226 are_secure_codecs_required_ = true; | 224 are_secure_codecs_required_ = true; |
227 return; | 225 return; |
| 226 #endif // defined(OS_ANDROID) |
228 case EmeConfigRule::SUPPORTED: | 227 case EmeConfigRule::SUPPORTED: |
229 return; | 228 return; |
230 } | 229 } |
231 NOTREACHED(); | 230 NOTREACHED(); |
232 } | 231 } |
233 | 232 |
234 private: | 233 private: |
235 // Whether permission to use a distinctive identifier was requested. If set, | 234 // Whether permission to use a distinctive identifier was requested. If set, |
236 // |is_permission_granted_| represents the final decision. | 235 // |is_permission_granted_| represents the final decision. |
237 // (Not changed by adding rules.) | 236 // (Not changed by adding rules.) |
238 bool was_permission_requested_; | 237 bool was_permission_requested_; |
239 | 238 |
240 // Whether permission to use a distinctive identifier has been granted. | 239 // Whether permission to use a distinctive identifier has been granted. |
241 // (Not changed by adding rules.) | 240 // (Not changed by adding rules.) |
242 bool is_permission_granted_; | 241 bool is_permission_granted_; |
243 | 242 |
244 // Whether a rule has been added that requires or blocks a distinctive | 243 // Whether a rule has been added that requires or blocks a distinctive |
245 // identifier. | 244 // identifier. |
246 bool is_identifier_required_ = false; | 245 bool is_identifier_required_ = false; |
247 bool is_identifier_not_allowed_ = false; | 246 bool is_identifier_not_allowed_ = false; |
248 | 247 |
249 // Whether a rule has been added that recommends a distinctive identifier. | 248 // Whether a rule has been added that recommends a distinctive identifier. |
250 bool is_identifier_recommended_ = false; | 249 bool is_identifier_recommended_ = false; |
251 | 250 |
252 // Whether a rule has been added that requires or blocks persistent state. | 251 // Whether a rule has been added that requires or blocks persistent state. |
253 bool is_persistence_required_ = false; | 252 bool is_persistence_required_ = false; |
254 bool is_persistence_not_allowed_ = false; | 253 bool is_persistence_not_allowed_ = false; |
255 | 254 |
256 // Whether a rule has been added that requires or blocks hardware-secure | 255 #if defined(OS_ANDROID) |
257 // codecs. | 256 // Whether a rule has been added that requires or blocks secure codecs. |
258 bool are_secure_codecs_required_ = false; | 257 bool are_secure_codecs_required_ = false; |
259 bool are_secure_codecs_not_allowed_ = false; | 258 bool are_secure_codecs_not_allowed_ = false; |
| 259 #endif // defined(OS_ANDROID) |
260 }; | 260 }; |
261 | 261 |
262 KeySystemConfigSelector::KeySystemConfigSelector( | 262 KeySystemConfigSelector::KeySystemConfigSelector( |
263 const KeySystems* key_systems, | 263 const KeySystems* key_systems, |
264 MediaPermission* media_permission) | 264 MediaPermission* media_permission) |
265 : key_systems_(key_systems), | 265 : key_systems_(key_systems), |
266 media_permission_(media_permission), | 266 media_permission_(media_permission), |
267 weak_factory_(this) { | 267 weak_factory_(this) { |
268 DCHECK(key_systems_); | 268 DCHECK(key_systems_); |
269 DCHECK(media_permission_); | 269 DCHECK(media_permission_); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 // 5. Return media type capabilities. | 385 // 5. Return media type capabilities. |
386 return true; | 386 return true; |
387 } | 387 } |
388 | 388 |
389 KeySystemConfigSelector::ConfigurationSupport | 389 KeySystemConfigSelector::ConfigurationSupport |
390 KeySystemConfigSelector::GetSupportedConfiguration( | 390 KeySystemConfigSelector::GetSupportedConfiguration( |
391 const std::string& key_system, | 391 const std::string& key_system, |
392 const blink::WebMediaKeySystemConfiguration& candidate, | 392 const blink::WebMediaKeySystemConfiguration& candidate, |
393 ConfigState* config_state, | 393 ConfigState* config_state, |
394 blink::WebMediaKeySystemConfiguration* accumulated_configuration) { | 394 blink::WebMediaKeySystemConfiguration* accumulated_configuration) { |
| 395 // TODO(sandersd): Set state of SECURE_CODECS from renderer pref. |
395 // From https://w3c.github.io/encrypted-media/#get-supported-configuration | 396 // From https://w3c.github.io/encrypted-media/#get-supported-configuration |
396 // 1. Let accumulated configuration be empty. (Done by caller.) | 397 // 1. Let accumulated configuration be empty. (Done by caller.) |
397 // 2. If the initDataTypes member is present in candidate configuration, run | 398 // 2. If the initDataTypes member is present in candidate configuration, run |
398 // the following steps: | 399 // the following steps: |
399 if (candidate.hasInitDataTypes) { | 400 if (candidate.hasInitDataTypes) { |
400 // 2.1. Let supported types be empty. | 401 // 2.1. Let supported types be empty. |
401 std::vector<blink::WebEncryptedMediaInitDataType> supported_types; | 402 std::vector<blink::WebEncryptedMediaInitDataType> supported_types; |
402 | 403 |
403 // 2.2. For each value in candidate configuration's initDataTypes member: | 404 // 2.2. For each value in candidate configuration's initDataTypes member: |
404 for (size_t i = 0; i < candidate.initDataTypes.size(); i++) { | 405 for (size_t i = 0; i < candidate.initDataTypes.size(); i++) { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 | 666 |
666 // 17. Return accumulated configuration. | 667 // 17. Return accumulated configuration. |
667 return CONFIGURATION_SUPPORTED; | 668 return CONFIGURATION_SUPPORTED; |
668 } | 669 } |
669 | 670 |
670 void KeySystemConfigSelector::SelectConfig( | 671 void KeySystemConfigSelector::SelectConfig( |
671 const blink::WebString& key_system, | 672 const blink::WebString& key_system, |
672 const blink::WebVector<blink::WebMediaKeySystemConfiguration>& | 673 const blink::WebVector<blink::WebMediaKeySystemConfiguration>& |
673 candidate_configurations, | 674 candidate_configurations, |
674 const blink::WebSecurityOrigin& security_origin, | 675 const blink::WebSecurityOrigin& security_origin, |
675 bool are_secure_codecs_supported, | 676 base::Callback<void(const blink::WebMediaKeySystemConfiguration&)> |
676 base::Callback<void(const blink::WebMediaKeySystemConfiguration&, bool)> | |
677 succeeded_cb, | 677 succeeded_cb, |
678 base::Callback<void(const blink::WebString&)> not_supported_cb) { | 678 base::Callback<void(const blink::WebString&)> not_supported_cb) { |
679 // Continued from requestMediaKeySystemAccess(), step 7, from | 679 // Continued from requestMediaKeySystemAccess(), step 7, from |
680 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess | 680 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess |
681 // | 681 // |
682 // 7.1. If keySystem is not one of the Key Systems supported by the user | 682 // 7.1. If keySystem is not one of the Key Systems supported by the user |
683 // agent, reject promise with with a new DOMException whose name is | 683 // agent, reject promise with with a new DOMException whose name is |
684 // NotSupportedError. String comparison is case-sensitive. | 684 // NotSupportedError. String comparison is case-sensitive. |
685 if (!base::IsStringASCII(key_system)) { | 685 if (!base::IsStringASCII(key_system)) { |
686 not_supported_cb.Run("Only ASCII keySystems are supported"); | 686 not_supported_cb.Run("Only ASCII keySystems are supported"); |
687 return; | 687 return; |
688 } | 688 } |
689 | 689 |
690 std::string key_system_ascii = base::UTF16ToASCII(key_system); | 690 std::string key_system_ascii = base::UTF16ToASCII(key_system); |
691 if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) { | 691 if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) { |
692 not_supported_cb.Run("Unsupported keySystem"); | 692 not_supported_cb.Run("Unsupported keySystem"); |
693 return; | 693 return; |
694 } | 694 } |
695 | 695 |
696 // 7.2-7.4. Implemented by OnSelectConfig(). | 696 // 7.2-7.4. Implemented by OnSelectConfig(). |
697 // TODO(sandersd): This should be async, ideally not on the main thread. | 697 // TODO(sandersd): This should be async, ideally not on the main thread. |
698 scoped_ptr<SelectionRequest> request(new SelectionRequest()); | 698 scoped_ptr<SelectionRequest> request(new SelectionRequest()); |
699 request->key_system = key_system_ascii; | 699 request->key_system = key_system_ascii; |
700 request->candidate_configurations = candidate_configurations; | 700 request->candidate_configurations = candidate_configurations; |
701 request->security_origin = security_origin; | 701 request->security_origin = security_origin; |
702 request->are_secure_codecs_supported = are_secure_codecs_supported; | |
703 request->succeeded_cb = succeeded_cb; | 702 request->succeeded_cb = succeeded_cb; |
704 request->not_supported_cb = not_supported_cb; | 703 request->not_supported_cb = not_supported_cb; |
705 SelectConfigInternal(request.Pass()); | 704 SelectConfigInternal(request.Pass()); |
706 } | 705 } |
707 | 706 |
708 void KeySystemConfigSelector::SelectConfigInternal( | 707 void KeySystemConfigSelector::SelectConfigInternal( |
709 scoped_ptr<SelectionRequest> request) { | 708 scoped_ptr<SelectionRequest> request) { |
710 // Continued from requestMediaKeySystemAccess(), step 7.1, from | 709 // Continued from requestMediaKeySystemAccess(), step 7.1, from |
711 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess | 710 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess |
712 // | 711 // |
713 // 7.2. Let implementation be the implementation of keySystem. | 712 // 7.2. Let implementation be the implementation of keySystem. |
714 // (|key_systems_| fills this role.) | 713 // (|key_systems_| fills this role.) |
715 // 7.3. For each value in supportedConfigurations: | 714 // 7.3. For each value in supportedConfigurations: |
716 for (size_t i = 0; i < request->candidate_configurations.size(); i++) { | 715 for (size_t i = 0; i < request->candidate_configurations.size(); i++) { |
717 // 7.3.1. Let candidate configuration be the value. | 716 // 7.3.1. Let candidate configuration be the value. |
718 // 7.3.2. Let supported configuration be the result of executing the Get | 717 // 7.3.2. Let supported configuration be the result of executing the Get |
719 // Supported Configuration algorithm on implementation, candidate | 718 // Supported Configuration algorithm on implementation, candidate |
720 // configuration, and origin. | 719 // configuration, and origin. |
721 // 7.3.3. If supported configuration is not null, [initialize and return a | 720 // 7.3.3. If supported configuration is not null, [initialize and return a |
722 // new MediaKeySystemAccess object.] | 721 // new MediaKeySystemAccess object.] |
723 ConfigState config_state(request->was_permission_requested, | 722 ConfigState config_state(request->was_permission_requested, |
724 request->is_permission_granted); | 723 request->is_permission_granted); |
725 DCHECK(config_state.IsRuleSupported( | |
726 EmeConfigRule::SECURE_CODECS_NOT_ALLOWED)); | |
727 if (!request->are_secure_codecs_supported) | |
728 config_state.AddRule(EmeConfigRule::SECURE_CODECS_NOT_ALLOWED); | |
729 blink::WebMediaKeySystemConfiguration accumulated_configuration; | 724 blink::WebMediaKeySystemConfiguration accumulated_configuration; |
730 ConfigurationSupport support = GetSupportedConfiguration( | 725 ConfigurationSupport support = GetSupportedConfiguration( |
731 request->key_system, request->candidate_configurations[i], | 726 request->key_system, request->candidate_configurations[i], |
732 &config_state, &accumulated_configuration); | 727 &config_state, &accumulated_configuration); |
733 switch (support) { | 728 switch (support) { |
734 case CONFIGURATION_NOT_SUPPORTED: | 729 case CONFIGURATION_NOT_SUPPORTED: |
735 continue; | 730 continue; |
736 case CONFIGURATION_REQUIRES_PERMISSION: | 731 case CONFIGURATION_REQUIRES_PERMISSION: |
737 if (request->was_permission_requested) { | 732 if (request->was_permission_requested) { |
738 DVLOG(2) << "Rejecting requested configuration because " | 733 DVLOG(2) << "Rejecting requested configuration because " |
739 << "permission was denied."; | 734 << "permission was denied."; |
740 continue; | 735 continue; |
741 } | 736 } |
742 media_permission_->RequestPermission( | 737 media_permission_->RequestPermission( |
743 MediaPermission::PROTECTED_MEDIA_IDENTIFIER, | 738 MediaPermission::PROTECTED_MEDIA_IDENTIFIER, |
744 GURL(request->security_origin.toString()), | 739 GURL(request->security_origin.toString()), |
745 base::Bind(&KeySystemConfigSelector::OnPermissionResult, | 740 base::Bind(&KeySystemConfigSelector::OnPermissionResult, |
746 weak_factory_.GetWeakPtr(), base::Passed(&request))); | 741 weak_factory_.GetWeakPtr(), base::Passed(&request))); |
747 return; | 742 return; |
748 case CONFIGURATION_SUPPORTED: | 743 case CONFIGURATION_SUPPORTED: |
749 request->succeeded_cb.Run(accumulated_configuration, | 744 request->succeeded_cb.Run(accumulated_configuration); |
750 config_state.AreSecureCodecsRequired()); | |
751 return; | 745 return; |
752 } | 746 } |
753 } | 747 } |
754 | 748 |
755 // 7.4. Reject promise with a new DOMException whose name is | 749 // 7.4. Reject promise with a new DOMException whose name is |
756 // NotSupportedError. | 750 // NotSupportedError. |
757 request->not_supported_cb.Run( | 751 request->not_supported_cb.Run( |
758 "None of the requested configurations were supported."); | 752 "None of the requested configurations were supported."); |
759 } | 753 } |
760 | 754 |
761 void KeySystemConfigSelector::OnPermissionResult( | 755 void KeySystemConfigSelector::OnPermissionResult( |
762 scoped_ptr<SelectionRequest> request, | 756 scoped_ptr<SelectionRequest> request, |
763 bool is_permission_granted) { | 757 bool is_permission_granted) { |
764 request->was_permission_requested = true; | 758 request->was_permission_requested = true; |
765 request->is_permission_granted = is_permission_granted; | 759 request->is_permission_granted = is_permission_granted; |
766 SelectConfigInternal(request.Pass()); | 760 SelectConfigInternal(request.Pass()); |
767 } | 761 } |
768 | 762 |
769 } // namespace media | 763 } // namespace media |
OLD | NEW |