1 | /* |
2 | * Copyright (C) 2016 Metrological Group B.V. |
3 | * Copyright (C) 2016 Igalia S.L. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above |
12 | * copyright notice, this list of conditions and the following |
13 | * disclaimer in the documentation and/or other materials provided |
14 | * with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include "config.h" |
30 | #include "NavigatorEME.h" |
31 | |
32 | #if ENABLE(ENCRYPTED_MEDIA) |
33 | |
34 | #include "CDM.h" |
35 | #include "Document.h" |
36 | #include "JSMediaKeySystemAccess.h" |
37 | #include "Logging.h" |
38 | |
39 | namespace WebCore { |
40 | |
41 | static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&&); |
42 | |
43 | void NavigatorEME::requestMediaKeySystemAccess(Navigator&, Document& document, const String& keySystem, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, Ref<DeferredPromise>&& promise) |
44 | { |
45 | // https://w3c.github.io/encrypted-media/#dom-navigator-requestmediakeysystemaccess |
46 | // W3C Editor's Draft 09 November 2016 |
47 | LOG(EME, "EME - request media key system access for %s" , keySystem.utf8().data()); |
48 | |
49 | // When this method is invoked, the user agent must run the following steps: |
50 | // 1. If keySystem is the empty string, return a promise rejected with a newly created TypeError. |
51 | // 2. If supportedConfigurations is empty, return a promise rejected with a newly created TypeError. |
52 | if (keySystem.isEmpty() || supportedConfigurations.isEmpty()) { |
53 | promise->reject(TypeError); |
54 | return; |
55 | } |
56 | |
57 | document.postTask([keySystem, supportedConfigurations = WTFMove(supportedConfigurations), promise = WTFMove(promise), &document] (ScriptExecutionContext&) mutable { |
58 | // 3. Let document be the calling context's Document. |
59 | // 4. Let origin be the origin of document. |
60 | // 5. Let promise be a new promise. |
61 | // 6. Run the following steps in parallel: |
62 | // 6.1. If keySystem is not one of the Key Systems supported by the user agent, reject promise with a NotSupportedError. |
63 | // String comparison is case-sensitive. |
64 | if (!CDM::supportsKeySystem(keySystem)) { |
65 | LOG(EME, "EME - %s is not supported" , keySystem.utf8().data()); |
66 | promise->reject(NotSupportedError); |
67 | return; |
68 | } |
69 | |
70 | // 6.2. Let implementation be the implementation of keySystem. |
71 | auto implementation = CDM::create(document, keySystem); |
72 | tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise)); |
73 | }); |
74 | } |
75 | |
76 | static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&& promise) |
77 | { |
78 | // 6.3. For each value in supportedConfigurations: |
79 | if (!supportedConfigurations.isEmpty()) { |
80 | // 6.3.1. Let candidate configuration be the value. |
81 | // 6.3.2. Let supported configuration be the result of executing the Get Supported Configuration |
82 | // algorithm on implementation, candidate configuration, and origin. |
83 | MediaKeySystemConfiguration candidateConfiguration = WTFMove(supportedConfigurations.first()); |
84 | supportedConfigurations.remove(0); |
85 | |
86 | CDM::SupportedConfigurationCallback callback = [implementation = implementation, supportedConfigurations = WTFMove(supportedConfigurations), promise] (Optional<MediaKeySystemConfiguration> supportedConfiguration) mutable { |
87 | // 6.3.3. If supported configuration is not NotSupported, run the following steps: |
88 | if (supportedConfiguration) { |
89 | // 6.3.3.1. Let access be a new MediaKeySystemAccess object, and initialize it as follows: |
90 | // 6.3.3.1.1. Set the keySystem attribute to keySystem. |
91 | // 6.3.3.1.2. Let the configuration value be supported configuration. |
92 | // 6.3.3.1.3. Let the cdm implementation value be implementation. |
93 | |
94 | // Obtain reference to the key system string before the `implementation` RefPtr<> is cleared out. |
95 | const String& keySystem = implementation->keySystem(); |
96 | auto access = MediaKeySystemAccess::create(keySystem, WTFMove(supportedConfiguration.value()), implementation.releaseNonNull()); |
97 | |
98 | // 6.3.3.2. Resolve promise with access and abort the parallel steps of this algorithm. |
99 | promise->resolveWithNewlyCreated<IDLInterface<MediaKeySystemAccess>>(WTFMove(access)); |
100 | return; |
101 | } |
102 | |
103 | tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise)); |
104 | }; |
105 | implementation->getSupportedConfiguration(WTFMove(candidateConfiguration), WTFMove(callback)); |
106 | return; |
107 | } |
108 | |
109 | |
110 | // 6.4. Reject promise with a NotSupportedError. |
111 | promise->reject(NotSupportedError); |
112 | } |
113 | |
114 | } // namespace WebCore |
115 | |
116 | #endif // ENABLE(ENCRYPTED_MEDIA) |
117 | |