Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237778 => 237779)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2018-11-04 10:28:11 UTC (rev 237779)
@@ -1,5 +1,15 @@
2018-11-04 Youenn Fablet <[email protected]>
+ IDB should allow storing RTCCertificate
+ https://bugs.webkit.org/show_bug.cgi?id=191077
+
+ Reviewed by Chris Dumez.
+
+ * web-platform-tests/webrtc/RTCCertificate-postMessage.html: Added.
+ * web-platform-tests/webrtc/resources/RTCCertificate-postMessage-iframe.html: Added.
+
+2018-11-04 Youenn Fablet <[email protected]>
+
Add support for RTCMuxPolicy
https://bugs.webkit.org/show_bug.cgi?id=191188
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCCertificate-postMessage.html (0 => 237779)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCCertificate-postMessage.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCCertificate-postMessage.html 2018-11-04 10:28:11 UTC (rev 237779)
@@ -0,0 +1,77 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>RTCCertificate persistent Tests</title>
+<script src=""
+<script src=""
+<script src=""
+<body>
+<script>
+ function findMatchingFingerprint(fingerprints, fingerprint) {
+ for (let f of fingerprints) {
+ if (f.value == fingerprint.value && f.algorithm == fingerprint.algorithm)
+ return true;
+ }
+ return false;
+ }
+
+ function with_iframe(url) {
+ return new Promise(function(resolve) {
+ var frame = document.createElement('iframe');
+ frame.src = ""
+ frame._onload_ = function() { resolve(frame); };
+ document.body.appendChild(frame);
+ });
+ }
+
+ function testPostMessageCertificate(isCrossOrigin) {
+ promise_test(async t => {
+ let certificate = await RTCPeerConnection.generateCertificate({ name: 'ECDSA', namedCurve: 'P-256' });
+
+ let url = ""
+ if (isCrossOrigin)
+ url = "" + "/webrtc/" + url;
+
+ let iframe = await with_iframe(url);
+
+ let promise = new Promise((resolve, reject) => {
+ window._onmessage_ = (event) => {
+ resolve(event.data);
+ };
+ t.step_timeout(() => reject("Timed out waiting for frame to send back certificate"), 5000);
+ });
+ iframe.contentWindow.postMessage(certificate, "*");
+ let certificate2 = await promise;
+
+ new RTCPeerConnection({certificates: [certificate]});
+
+ new RTCPeerConnection({certificates: [certificate2]});
+
+ assert_equals(certificate.expires, certificate2.expires);
+ for (let fingerprint of certificate2.getFingerprints())
+ assert_true(findMatchingFingerprint(certificate.getFingerprints(), fingerprint), "check fingerprints");
+
+ iframe.remove();
+ }, "Check " + (isCrossOrigin ? "cross-origin" : "same-origin") + " RTCCertificate serialization");
+ }
+
+ testPostMessageCertificate(false);
+ testPostMessageCertificate(true);
+
+ promise_test(async t => {
+ let url = "" + "/webrtc/resources/RTCCertificate-postMessage-iframe.html";
+ let iframe = await with_iframe(url);
+
+ let promise = new Promise((resolve, reject) => {
+ window._onmessage_ = (event) => {
+ resolve(event.data);
+ };
+ t.step_timeout(() => reject("Timed out waiting for frame to send back certificate"), 5000);
+ });
+ iframe.contentWindow.postMessage(null, "*");
+ let certificate2 = await promise;
+
+ assert_throws("InvalidAccessError", () => { new RTCPeerConnection({certificates: [certificate2]}) });
+ iframe.remove();
+ }, "Check cross-origin created RTCCertificate");
+</script>
+</body>
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/resources/RTCCertificate-postMessage-iframe.html (0 => 237779)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/resources/RTCCertificate-postMessage-iframe.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/resources/RTCCertificate-postMessage-iframe.html 2018-11-04 10:28:11 UTC (rev 237779)
@@ -0,0 +1,9 @@
+<!doctype html>
+<script>
+window._onmessage_ = async (event) => {
+ let certificate = event.data;
+ if (!certificate)
+ certificate = await RTCPeerConnection.generateCertificate({ name: 'ECDSA', namedCurve: 'P-256'});
+ event.source.postMessage(certificate, "*");
+}
+</script>
Modified: trunk/Source/WebCore/ChangeLog (237778 => 237779)
--- trunk/Source/WebCore/ChangeLog 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/ChangeLog 2018-11-04 10:28:11 UTC (rev 237779)
@@ -1,5 +1,38 @@
2018-11-04 Youenn Fablet <[email protected]>
+ IDB should allow storing RTCCertificate
+ https://bugs.webkit.org/show_bug.cgi?id=191077
+
+ Reviewed by Chris Dumez.
+
+ Add support for serialization/deserialization of RTCCertificate.
+ Store the origin in RTCCertificate and make sure that a certificate
+ with a different origin cannot be used to create a RTCPeerConnection.
+
+ Test: imported/w3c/web-platform-tests/webrtc/RTCCertificate-postMessage.html
+
+ * Modules/mediastream/PeerConnectionBackend.cpp:
+ (WebCore::PeerConnectionBackend::generateCertificate):
+ * Modules/mediastream/RTCCertificate.cpp:
+ (WebCore::RTCCertificate::create):
+ (WebCore::RTCCertificate::RTCCertificate):
+ * Modules/mediastream/RTCCertificate.h:
+ (WebCore::RTCCertificate::origin const):
+ * Modules/mediastream/RTCPeerConnection.cpp:
+ (WebCore::RTCPeerConnection::certificatesFromConfiguration):
+ * Modules/mediastream/RTCPeerConnection.h:
+ * Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp:
+ (WebCore::LibWebRTCCertificateGenerator::RTCCertificateGeneratorCallback::RTCCertificateGeneratorCallback):
+ (WebCore::LibWebRTCCertificateGenerator::generateCertificate):
+ * Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.h:
+ * bindings/js/SerializedScriptValue.cpp:
+ (WebCore::CloneSerializer::dumpIfTerminal):
+ (WebCore::CloneDeserializer::CachedString::takeString):
+ (WebCore::CloneDeserializer::readRTCCertificate):
+ (WebCore::CloneDeserializer::readTerminal):
+
+2018-11-04 Youenn Fablet <[email protected]>
+
Add support for RTCMuxPolicy
https://bugs.webkit.org/show_bug.cgi?id=191188
Modified: trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp 2018-11-04 10:28:11 UTC (rev 237779)
@@ -517,7 +517,7 @@
void PeerConnectionBackend::generateCertificate(Document& document, const CertificateInformation& info, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
{
#if USE(LIBWEBRTC)
- LibWebRTCCertificateGenerator::generateCertificate(document.page()->libWebRTCProvider(), info, WTFMove(promise));
+ LibWebRTCCertificateGenerator::generateCertificate(document.securityOrigin(), document.page()->libWebRTCProvider(), info, WTFMove(promise));
#else
UNUSED_PARAM(document);
UNUSED_PARAM(expires);
Modified: trunk/Source/WebCore/Modules/mediastream/RTCCertificate.cpp (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/RTCCertificate.cpp 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/RTCCertificate.cpp 2018-11-04 10:28:11 UTC (rev 237779)
@@ -29,13 +29,14 @@
namespace WebCore {
-Ref<RTCCertificate> RTCCertificate::create(double expires, Vector<DtlsFingerprint>&& fingerprints, String&& pemCertificate, String&& pemPrivateKey)
+Ref<RTCCertificate> RTCCertificate::create(Ref<SecurityOrigin>&& origin, double expires, Vector<DtlsFingerprint>&& fingerprints, String&& pemCertificate, String&& pemPrivateKey)
{
- return adoptRef(*new RTCCertificate(expires, WTFMove(fingerprints), WTFMove(pemCertificate), WTFMove(pemPrivateKey)));
+ return adoptRef(*new RTCCertificate(WTFMove(origin), expires, WTFMove(fingerprints), WTFMove(pemCertificate), WTFMove(pemPrivateKey)));
}
-RTCCertificate::RTCCertificate(double expires, Vector<DtlsFingerprint>&& fingerprints, String&& pemCertificate, String&& pemPrivateKey)
- : m_expires(expires)
+RTCCertificate::RTCCertificate(Ref<SecurityOrigin>&& origin, double expires, Vector<DtlsFingerprint>&& fingerprints, String&& pemCertificate, String&& pemPrivateKey)
+ : m_origin(WTFMove(origin))
+ , m_expires(expires)
, m_fingerprints(WTFMove(fingerprints))
, m_pemCertificate(WTFMove(pemCertificate))
, m_pemPrivateKey(WTFMove(pemPrivateKey))
Modified: trunk/Source/WebCore/Modules/mediastream/RTCCertificate.h (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/RTCCertificate.h 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/RTCCertificate.h 2018-11-04 10:28:11 UTC (rev 237779)
@@ -26,6 +26,7 @@
#if ENABLE(WEB_RTC)
+#include "SecurityOrigin.h"
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -38,7 +39,7 @@
String value;
};
- static Ref<RTCCertificate> create(double expires, Vector<DtlsFingerprint>&&, String&& pemCertificate, String&& pemPrivateKey);
+ static Ref<RTCCertificate> create(Ref<SecurityOrigin>&&, double expires, Vector<DtlsFingerprint>&&, String&& pemCertificate, String&& pemPrivateKey);
double expires() const { return m_expires; }
const Vector<DtlsFingerprint>& getFingerprints() const { return m_fingerprints; }
@@ -45,10 +46,12 @@
const String& pemCertificate() const { return m_pemCertificate; }
const String& pemPrivateKey() const { return m_pemPrivateKey; }
+ const SecurityOrigin& origin() const { return m_origin.get(); }
private:
- RTCCertificate(double expires, Vector<DtlsFingerprint>&&, String&& pemCertificate, String&& pemPrivateKey);
+ RTCCertificate(Ref<SecurityOrigin>&&, double expires, Vector<DtlsFingerprint>&&, String&& pemCertificate, String&& pemPrivateKey);
+ Ref<SecurityOrigin> m_origin;
double m_expires { 0 };
Vector<DtlsFingerprint> m_fingerprints;
String m_pemCertificate;
Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp 2018-11-04 10:28:11 UTC (rev 237779)
@@ -297,18 +297,23 @@
return WTFMove(servers);
}
-static inline ExceptionOr<Vector<MediaEndpointConfiguration::CertificatePEM>> certificatesFromConfiguration(const RTCConfiguration& configuration)
+ExceptionOr<Vector<MediaEndpointConfiguration::CertificatePEM>> RTCPeerConnection::certificatesFromConfiguration(const RTCConfiguration& configuration)
{
- std::optional<Exception> exception;
auto currentMilliSeconds = WallTime::now().secondsSinceEpoch().milliseconds();
- auto result = WTF::map(configuration.certificates, [&](const auto& certificate) {
- if (!exception && currentMilliSeconds > certificate->expires())
- exception = Exception { InvalidAccessError, "Certificate has expired"_s };
- return MediaEndpointConfiguration::CertificatePEM { certificate->pemCertificate(), certificate->pemPrivateKey(), };
- });
- if (exception)
- return WTFMove(*exception);
- return WTFMove(result);
+ auto& origin = downcast<Document>(*scriptExecutionContext()).securityOrigin();
+
+ Vector<MediaEndpointConfiguration::CertificatePEM> certificates;
+ certificates.reserveInitialCapacity(configuration.certificates.size());
+ for (auto& certificate : configuration.certificates) {
+ if (!originsMatch(origin, certificate->origin()))
+ return Exception { InvalidAccessError, "Certificate does not have a valid origin" };
+
+ if (currentMilliSeconds > certificate->expires())
+ return Exception { InvalidAccessError, "Certificate has expired"_s };
+
+ certificates.uncheckedAppend(MediaEndpointConfiguration::CertificatePEM { certificate->pemCertificate(), certificate->pemPrivateKey(), });
+ }
+ return WTFMove(certificates);
}
ExceptionOr<void> RTCPeerConnection::initializeConfiguration(RTCConfiguration&& configuration)
Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h 2018-11-04 10:28:11 UTC (rev 237779)
@@ -37,6 +37,7 @@
#include "ActiveDOMObject.h"
#include "EventTarget.h"
+#include "MediaEndpointConfiguration.h"
#include "MediaStream.h"
#include "RTCConfiguration.h"
#include "RTCDataChannel.h"
@@ -201,6 +202,8 @@
bool doClose();
void doStop();
+ ExceptionOr<Vector<MediaEndpointConfiguration::CertificatePEM>> certificatesFromConfiguration(const RTCConfiguration&);
+
bool m_isStopped { false };
RTCSignalingState m_signalingState { RTCSignalingState::Stable };
RTCIceGatheringState m_iceGatheringState { RTCIceGatheringState::New };
Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp 2018-11-04 10:28:11 UTC (rev 237779)
@@ -47,8 +47,9 @@
class RTCCertificateGeneratorCallback : public ThreadSafeRefCounted<RTCCertificateGeneratorCallback, WTF::DestructionThread::Main>, public rtc::RTCCertificateGeneratorCallback {
public:
- explicit RTCCertificateGeneratorCallback(DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
- : m_promise(WTFMove(promise))
+ RTCCertificateGeneratorCallback(Ref<SecurityOrigin>&& origin, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
+ : m_origin(WTFMove(origin))
+ , m_promise(WTFMove(promise))
{
}
@@ -63,7 +64,7 @@
private:
void OnSuccess(const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) final
{
- callOnMainThread([promise = WTFMove(m_promise.value()), certificate]() mutable {
+ callOnMainThread([origin = m_origin.releaseNonNull(), promise = WTFMove(m_promise.value()), certificate]() mutable {
Vector<RTCCertificate::DtlsFingerprint> fingerprints;
auto stats = certificate->ssl_certificate().GetStats();
auto* info = stats.get();
@@ -74,7 +75,7 @@
};
auto pem = certificate->ToPEM();
- promise.resolve(RTCCertificate::create(certificate->Expires(), WTFMove(fingerprints), fromStdString(pem.certificate()), fromStdString(pem.private_key())));
+ promise.resolve(RTCCertificate::create(WTFMove(origin), certificate->Expires(), WTFMove(fingerprints), fromStdString(pem.certificate()), fromStdString(pem.private_key())));
});
}
@@ -85,6 +86,7 @@
});
}
+ RefPtr<SecurityOrigin> m_origin;
std::optional<DOMPromiseDeferred<IDLInterface<RTCCertificate>>> m_promise;
};
@@ -102,9 +104,9 @@
RELEASE_ASSERT_NOT_REACHED();
}
-void generateCertificate(LibWebRTCProvider& provider, const PeerConnectionBackend::CertificateInformation& info, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
+void generateCertificate(Ref<SecurityOrigin>&& origin, LibWebRTCProvider& provider, const PeerConnectionBackend::CertificateInformation& info, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
{
- rtc::scoped_refptr<RTCCertificateGeneratorCallback> callback(new RTCCertificateGeneratorCallback(WTFMove(promise)));
+ rtc::scoped_refptr<RTCCertificateGeneratorCallback> callback(new RTCCertificateGeneratorCallback(WTFMove(origin), WTFMove(promise)));
absl::optional<uint64_t> expiresMs;
if (info.expires)
Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.h (237778 => 237779)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.h 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.h 2018-11-04 10:28:11 UTC (rev 237779)
@@ -31,10 +31,11 @@
namespace WebCore {
class LibWebRTCProvider;
+class SecurityOrigin;
namespace LibWebRTCCertificateGenerator {
-void generateCertificate(LibWebRTCProvider&, const PeerConnectionBackend::CertificateInformation&, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&&);
+void generateCertificate(Ref<SecurityOrigin>&&, LibWebRTCProvider&, const PeerConnectionBackend::CertificateInformation&, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&&);
} // namespace LibWebRTCCertificateGenerator
Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (237778 => 237779)
--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp 2018-11-04 07:55:02 UTC (rev 237778)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp 2018-11-04 10:28:11 UTC (rev 237779)
@@ -50,6 +50,7 @@
#include "JSImageData.h"
#include "JSMessagePort.h"
#include "JSNavigator.h"
+#include "JSRTCCertificate.h"
#include "ScriptExecutionContext.h"
#include "ScriptState.h"
#include "SharedBuffer.h"
@@ -161,6 +162,9 @@
DOMMatrixTag = 41,
DOMQuadTag = 42,
ImageBitmapTransferTag = 43,
+#if ENABLE(WEB_RTC)
+ RTCCertificateTag = 44,
+#endif
ErrorTag = 255
};
@@ -342,7 +346,13 @@
* | DOMMatrix
* | DOMQuad
* | ImageBitmapTransferTag <value:uint32_t>
+ * | RTCCertificateTag
*
+ * Inside certificate, data is serialized in this format as per spec:
+ *
+ * <expires:double> <certificate:StringData> <origin:StringData> <keyingMaterial:StringData>
+ * We also add fingerprints to make sure we expose to _javascript_ the same information.
+ *
* Inside wrapped crypto key, data is serialized in this format:
*
* <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
@@ -1052,7 +1062,21 @@
return true;
}
#endif
-
+#if ENABLE(WEB_RTC)
+ if (auto* rtcCertificate = JSRTCCertificate::toWrapped(vm, obj)) {
+ write(RTCCertificateTag);
+ write(rtcCertificate->expires());
+ write(rtcCertificate->pemCertificate());
+ write(rtcCertificate->origin().toString());
+ write(rtcCertificate->pemPrivateKey());
+ write(static_cast<unsigned>(rtcCertificate->getFingerprints().size()));
+ for (const auto& fingerprint : rtcCertificate->getFingerprints()) {
+ write(fingerprint.algorithm);
+ write(fingerprint.value);
+ }
+ return true;
+ }
+#endif
#if ENABLE(WEBASSEMBLY)
if (JSWebAssemblyModule* module = jsDynamicCast<JSWebAssemblyModule*>(vm, obj)) {
if (m_context != SerializationContext::WorkerPostMessage && m_context != SerializationContext::WindowPostMessage)
@@ -1743,6 +1767,7 @@
return m_jsString;
}
const String& string() { return m_string; }
+ String takeString() { return WTFMove(m_string); }
private:
String m_string;
@@ -2649,6 +2674,50 @@
return getJSValue(bitmap);
}
+#if ENABLE(WEB_RTC)
+ JSValue readRTCCertificate()
+ {
+ double expires;
+ if (!read(expires)) {
+ fail();
+ return JSValue();
+ }
+ CachedStringRef certificate;
+ if (!readStringData(certificate)) {
+ fail();
+ return JSValue();
+ }
+ CachedStringRef origin;
+ if (!readStringData(origin)) {
+ fail();
+ return JSValue();
+ }
+ CachedStringRef keyedMaterial;
+ if (!readStringData(keyedMaterial)) {
+ fail();
+ return JSValue();
+ }
+ unsigned size = 0;
+ if (!read(size))
+ return JSValue();
+
+ Vector<RTCCertificate::DtlsFingerprint> fingerprints;
+ fingerprints.reserveInitialCapacity(size);
+ for (unsigned i = 0; i < size; i++) {
+ CachedStringRef algorithm;
+ if (!readStringData(algorithm))
+ return JSValue();
+ CachedStringRef value;
+ if (!readStringData(value))
+ return JSValue();
+ fingerprints.uncheckedAppend(RTCCertificate::DtlsFingerprint { algorithm->string(), value->string() });
+ }
+
+ auto rtcCertificate = RTCCertificate::create(SecurityOrigin::createFromString(origin->string()), expires, WTFMove(fingerprints), certificate->takeString(), keyedMaterial->takeString());
+ return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), WTFMove(rtcCertificate));
+ }
+#endif
+
JSValue readTerminal()
{
SerializationTag tag = readTag();
@@ -2939,6 +3008,11 @@
return readDOMQuad();
case ImageBitmapTransferTag:
return readImageBitmap();
+#if ENABLE(WEB_RTC)
+ case RTCCertificateTag:
+ return readRTCCertificate();
+
+#endif
default:
m_ptr--; // Push the tag back
return JSValue();