WebKit Bugzilla
Attachment 343508 Details for
Bug 186958
: Add API to control mock media devices
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-186958-20180625101710.patch (text/plain), 75.69 KB, created by
youenn fablet
on 2018-06-25 10:17:11 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2018-06-25 10:17:11 PDT
Size:
75.69 KB
patch
obsolete
>Subversion Revision: 233151 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index cc1d3347bf85b24e17cb989b2a92f8fd57cf45cb..fb9eeafa3106bea3097e3dac23c1702fbc5910bd 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,82 @@ >+2018-06-25 Youenn Fablet <youenn@apple.com> >+ >+ Add API to control mock media devices >+ https://bugs.webkit.org/show_bug.cgi?id=186958 >+ >+ Reviewed by Eric Carlson. >+ >+ Refactor code to introduce a MockDevice structure that can be used in multiple processes. >+ Update mock sources and center to use MockDevice. >+ Add API to update mock media devices. >+ >+ Make MediaDevices an ActiveDOMObject so that it does not get collected when ondevicechange is set. >+ >+ Test: fast/mediastream/device-change-event-2.html >+ >+ * Modules/mediastream/MediaDevices.cpp: >+ (WebCore::MediaDevices::MediaDevices): >+ (WebCore::MediaDevices::stop): >+ (WebCore::MediaDevices::scheduledEventTimerFired): >+ (WebCore::MediaDevices::hasPendingActivity const): >+ (WebCore::MediaDevices::activeDOMObjectName const): >+ (WebCore::MediaDevices::canSuspendForDocumentSuspension const): >+ * Modules/mediastream/MediaDevices.h: >+ * Modules/mediastream/MediaDevices.idl: >+ * WebCore.xcodeproj/project.pbxproj: >+ * platform/mediastream/RealtimeMediaSourceCenter.h: >+ * platform/mock/MockMediaDevice.h: Added. >+ (WebCore::MockMicrophoneProperties::encode const): >+ (WebCore::MockMicrophoneProperties::decode): >+ (WebCore::MockCameraProperties::encode const): >+ (WebCore::MockCameraProperties::decode): >+ (WebCore::MockDisplayProperties::encode const): >+ (WebCore::MockDisplayProperties::decode): >+ (WebCore::MockMediaDevice::isMicrophone const): >+ (WebCore::MockMediaDevice::isCamera const): >+ (WebCore::MockMediaDevice::isDisplay const): >+ (WebCore::MockMediaDevice::type const): >+ (WebCore::MockMediaDevice::encode const): >+ (WebCore::MockMediaDevice::decodeMockMediaDevice): >+ (WebCore::MockMediaDevice::decode): >+ * platform/mock/MockRealtimeAudioSource.cpp: >+ (WebCore::MockRealtimeAudioSource::startProducingData): >+ * platform/mock/MockRealtimeMediaSource.cpp: >+ (WebCore::defaultDevices): >+ (WebCore::devices): >+ (WebCore::deviceMap): >+ (WebCore::deviceListForDevice): >+ (WebCore::MockRealtimeMediaSource::createCaptureDevice): >+ (WebCore::MockRealtimeMediaSource::resetDevices): >+ (WebCore::MockRealtimeMediaSource::setDevices): >+ (WebCore::MockRealtimeMediaSource::addDevice): >+ (WebCore::MockRealtimeMediaSource::removeDevice): >+ (WebCore::MockRealtimeMediaSource::captureDeviceWithPersistentID): >+ (WebCore::MockRealtimeMediaSource::audioDevices): >+ (WebCore::MockRealtimeMediaSource::videoDevices): >+ (WebCore::MockRealtimeMediaSource::displayDevices): >+ (WebCore::MockRealtimeMediaSource::MockRealtimeMediaSource): >+ (WebCore::MockRealtimeMediaSource::initializeCapabilities): >+ (WebCore::MockRealtimeMediaSource::initializeSettings): >+ (WebCore::MockRealtimeMediaSource::settings const): >+ (WebCore::MockRealtimeMediaSource::supportedConstraints): >+ * platform/mock/MockRealtimeMediaSource.h: >+ (WebCore::MockRealtimeMediaSource::device const): >+ * platform/mock/MockRealtimeMediaSourceCenter.cpp: >+ (WebCore::MockRealtimeMediaSourceCenter::singleton): >+ (WebCore::MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled): >+ (WebCore::MockRealtimeMediaSourceCenter::setDevices): >+ (WebCore::MockRealtimeMediaSourceCenter::addDevice): >+ (WebCore::MockRealtimeMediaSourceCenter::removeDevice): >+ * platform/mock/MockRealtimeMediaSourceCenter.h: >+ * platform/mock/MockRealtimeVideoSource.cpp: >+ (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource): >+ (WebCore::MockRealtimeVideoSource::initializeCapabilities): >+ (WebCore::MockRealtimeVideoSource::drawText): >+ (WebCore::MockRealtimeVideoSource::generateFrame): >+ * platform/mock/MockRealtimeVideoSource.h: >+ (WebCore::MockRealtimeVideoSource::mockCamera const): >+ (WebCore::MockRealtimeVideoSource::mockScreen const): >+ > 2018-06-25 Simon Fraser <simon.fraser@apple.com> > > AutoTableLayout wastes 52KB of Vector capacity on nytimes.com >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index b5e2a49b559729d9fa5cde8c94c0a0b49111ec20..2f463881489b88c1f6295ab624c7333b3ec5f98d 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,36 @@ >+2018-06-25 Youenn Fablet <youenn@apple.com> >+ >+ Add API to control mock media devices >+ https://bugs.webkit.org/show_bug.cgi?id=186958 >+ >+ Reviewed by Eric Carlson. >+ >+ Add API to clear, set, remove and reset mock media devices. >+ The mock media center of UIProcess and all WebProcesses are updated. >+ >+ * CMakeLists.txt: >+ * UIProcess/API/C/WKMockMediaDevice.cpp: Added. >+ (typeFromString): >+ (WKAddMockMediaDevice): >+ (WKClearMockMediaDevices): >+ (WKRemoveMockMediaDevice): >+ (WKResetMockMediaDevices): >+ * UIProcess/API/C/WKMockMediaDevice.h: Added. >+ * UIProcess/WebProcessPool.cpp: >+ (WebKit::WebProcessPool::addMockMediaDevice): >+ (WebKit::WebProcessPool::clearMockMediaDevices): >+ (WebKit::WebProcessPool::removeMockMediaDevice): >+ (WebKit::WebProcessPool::resetMockMediaDevices): >+ * UIProcess/WebProcessPool.h: >+ * WebKit.xcodeproj/project.pbxproj: >+ * WebProcess/WebProcess.cpp: >+ (WebKit::WebProcess::addMockMediaDevice): >+ (WebKit::WebProcess::clearMockMediaDevices): >+ (WebKit::WebProcess::removeMockMediaDevice): >+ (WebKit::WebProcess::resetMockMediaDevices): >+ * WebProcess/WebProcess.h: >+ * WebProcess/WebProcess.messages.in: >+ > 2018-06-23 Brian Burg <bburg@apple.com> > > [Mac] Web Automation: include correct key code with synthesized NSEvents used for keystrokes >diff --git a/Source/WebCore/Modules/mediastream/MediaDevices.cpp b/Source/WebCore/Modules/mediastream/MediaDevices.cpp >index af3bf13229497c099554626ca2389ecb6aca1a85..be9051c93994d5bbc10a0d8aa69419b1714aeeab 100644 >--- a/Source/WebCore/Modules/mediastream/MediaDevices.cpp >+++ b/Source/WebCore/Modules/mediastream/MediaDevices.cpp >@@ -47,8 +47,9 @@ > namespace WebCore { > > inline MediaDevices::MediaDevices(Document& document) >- : ContextDestructionObserver(&document) >+ : ActiveDOMObject(&document) > , m_scheduledEventTimer(*this, &MediaDevices::scheduledEventTimerFired) >+ , m_eventNames(eventNames()) > { > m_deviceChangedToken = RealtimeMediaSourceCenter::singleton().addDevicesChangedObserver([weakThis = makeWeakPtr(*this), this]() { > >@@ -61,16 +62,20 @@ inline MediaDevices::MediaDevices(Document& document) > m_scheduledEventTimer.startOneShot(Seconds(randomNumber() / 2)); > }); > >+ suspendIfNeeded(); >+ > static_assert(static_cast<size_t>(MediaDevices::DisplayCaptureSurfaceType::Monitor) == static_cast<size_t>(RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor), "MediaDevices::DisplayCaptureSurfaceType::Monitor is not equal to RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor as expected"); > static_assert(static_cast<size_t>(MediaDevices::DisplayCaptureSurfaceType::Window) == static_cast<size_t>(RealtimeMediaSourceSettings::DisplaySurfaceType::Window), "MediaDevices::DisplayCaptureSurfaceType::Window is not RealtimeMediaSourceSettings::DisplaySurfaceType::Window as expected"); > static_assert(static_cast<size_t>(MediaDevices::DisplayCaptureSurfaceType::Application) == static_cast<size_t>(RealtimeMediaSourceSettings::DisplaySurfaceType::Application), "MediaDevices::DisplayCaptureSurfaceType::Application is not RealtimeMediaSourceSettings::DisplaySurfaceType::Application as expected"); > static_assert(static_cast<size_t>(MediaDevices::DisplayCaptureSurfaceType::Browser) == static_cast<size_t>(RealtimeMediaSourceSettings::DisplaySurfaceType::Browser), "MediaDevices::DisplayCaptureSurfaceType::Browser is not RealtimeMediaSourceSettings::DisplaySurfaceType::Browser as expected"); > } > >-MediaDevices::~MediaDevices() >+MediaDevices::~MediaDevices() = default; >+ >+void MediaDevices::stop() > { > if (m_deviceChangedToken) >- RealtimeMediaSourceCenter::singleton().removeDevicesChangedObserver(m_deviceChangedToken.value()); >+ RealtimeMediaSourceCenter::singleton().removeDevicesChangedObserver(m_deviceChangedToken); > } > > Ref<MediaDevices> MediaDevices::create(Document& document) >@@ -157,7 +162,23 @@ MediaTrackSupportedConstraints MediaDevices::getSupportedConstraints() > > void MediaDevices::scheduledEventTimerFired() > { >- dispatchEvent(Event::create(eventNames().devicechangeEvent, false, false)); >+ if (scriptExecutionContext()) >+ dispatchEvent(Event::create(eventNames().devicechangeEvent, false, false)); >+} >+ >+bool MediaDevices::hasPendingActivity() const >+{ >+ return scriptExecutionContext() && hasEventListeners(m_eventNames.devicechangeEvent); >+} >+ >+const char* MediaDevices::activeDOMObjectName() const >+{ >+ return "MediaDevices"; >+} >+ >+bool MediaDevices::canSuspendForDocumentSuspension() const >+{ >+ return true; > } > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/mediastream/MediaDevices.h b/Source/WebCore/Modules/mediastream/MediaDevices.h >index ae35d5e94d0ba76910154e8dc10ee3da8ff8604e..02d1aef9d6f317867a97f195be90614859549cf5 100644 >--- a/Source/WebCore/Modules/mediastream/MediaDevices.h >+++ b/Source/WebCore/Modules/mediastream/MediaDevices.h >@@ -33,6 +33,8 @@ > > #if ENABLE(MEDIA_STREAM) > >+#include "ActiveDOMObject.h" >+#include "EventNames.h" > #include "EventTarget.h" > #include "ExceptionOr.h" > #include "JSDOMPromiseDeferred.h" >@@ -49,7 +51,7 @@ class MediaStream; > > struct MediaTrackSupportedConstraints; > >-class MediaDevices : public RefCounted<MediaDevices>, public ContextDestructionObserver, public EventTargetWithInlineData, public CanMakeWeakPtr<MediaDevices> { >+class MediaDevices : public RefCounted<MediaDevices>, public ActiveDOMObject, public EventTargetWithInlineData, public CanMakeWeakPtr<MediaDevices> { > public: > static Ref<MediaDevices> create(Document&); > >@@ -84,14 +86,23 @@ private: > > void scheduledEventTimerFired(); > >+ friend class JSMediaDevicesOwner; >+ >+ // ActiveDOMObject >+ const char* activeDOMObjectName() const final; >+ bool canSuspendForDocumentSuspension() const final; >+ void stop() final; >+ bool hasPendingActivity() const final; >+ > // EventTargetWithInlineData. >- EventTargetInterface eventTargetInterface() const override { return MediaDevicesEventTargetInterfaceType; } >- ScriptExecutionContext* scriptExecutionContext() const final { return m_scriptExecutionContext; } >- void refEventTarget() override { ref(); } >- void derefEventTarget() override { deref(); } >+ EventTargetInterface eventTargetInterface() const final { return MediaDevicesEventTargetInterfaceType; } >+ ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); } >+ void refEventTarget() final { ref(); } >+ void derefEventTarget() final { deref(); } > > Timer m_scheduledEventTimer; >- std::optional<RealtimeMediaSourceCenter::DevicesChangedObserverToken> m_deviceChangedToken; >+ RealtimeMediaSourceCenter::DevicesChangedObserverToken m_deviceChangedToken; >+ const EventNames& m_eventNames; // Need to cache this so we can use it from GC threads. > }; > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/mediastream/MediaDevices.idl b/Source/WebCore/Modules/mediastream/MediaDevices.idl >index 31a04de1d4847e5e782c4c4393071c13309c2cd4..d7ba3ed241f223c274be8bb37b346ffecf3443fb 100644 >--- a/Source/WebCore/Modules/mediastream/MediaDevices.idl >+++ b/Source/WebCore/Modules/mediastream/MediaDevices.idl >@@ -30,6 +30,7 @@ > > // FIXME 169871: should be subclass of EventTarget > [ >+ ActiveDOMObject, > Conditional=MEDIA_STREAM, > NoInterfaceObject, > ] interface MediaDevices { >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 206c49574831d0cd280326d66cb6f02943ab77bf..f6836a6f89935d8b75ae7e60080c03e71652fa76 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -1064,6 +1064,7 @@ > 4138D3351244054800323D33 /* EventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4138D3331244054800323D33 /* EventContext.h */; }; > 4138F8581D253F0E001CB61E /* JSDOMIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4138F8561D253EEE001CB61E /* JSDOMIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 413C2C341BC29A8F0075204C /* JSDOMConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 413C2C331BC29A7B0075204C /* JSDOMConstructor.h */; }; >+ 413CCD4A20DE034F0065A21A /* MockMediaDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 413CCD4820DE013C0065A21A /* MockMediaDevice.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 413E00791DB0E4F2002341D2 /* MemoryRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 413E00781DB0E4DE002341D2 /* MemoryRelease.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 414B82051D6DF0E50077EBE3 /* StructuredClone.h in Headers */ = {isa = PBXBuildFile; fileRef = 414B82031D6DF0D90077EBE3 /* StructuredClone.h */; }; > 414DEDE71F9FE91E0047C40D /* EmptyFrameLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 414DEDE51F9FE9150047C40D /* EmptyFrameLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -7202,6 +7203,7 @@ > 4138F8551D253EEE001CB61E /* JSDOMIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMIterator.cpp; sourceTree = "<group>"; }; > 4138F8561D253EEE001CB61E /* JSDOMIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMIterator.h; sourceTree = "<group>"; }; > 413C2C331BC29A7B0075204C /* JSDOMConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConstructor.h; sourceTree = "<group>"; }; >+ 413CCD4820DE013C0065A21A /* MockMediaDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockMediaDevice.h; sourceTree = "<group>"; }; > 413E00771DB0E4DE002341D2 /* MemoryRelease.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryRelease.cpp; sourceTree = "<group>"; }; > 413E00781DB0E4DE002341D2 /* MemoryRelease.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryRelease.h; sourceTree = "<group>"; }; > 413E007B1DB0E707002341D2 /* MemoryReleaseCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryReleaseCocoa.mm; sourceTree = "<group>"; }; >@@ -18774,6 +18776,7 @@ > 077B64151B95F703003E9AD5 /* MediaPlaybackTargetMock.h */, > 077B64101B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp */, > 077B64111B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h */, >+ 413CCD4820DE013C0065A21A /* MockMediaDevice.h */, > 07D6A4F11BED5F8800174146 /* MockRealtimeAudioSource.cpp */, > 07D6A4F21BED5F8800174146 /* MockRealtimeAudioSource.h */, > 07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */, >@@ -29423,6 +29426,7 @@ > CDF4B7201E03BF6F00E235A2 /* MockCDMFactory.idl in Headers */, > 51058AE01D67C229009A538C /* MockGamepad.h in Headers */, > 51058AE21D67C229009A538C /* MockGamepadProvider.h in Headers */, >+ 413CCD4A20DE034F0065A21A /* MockMediaDevice.h in Headers */, > CDF2B0131820540600F2B424 /* MockMediaPlayerMediaSource.h in Headers */, > CDF2B0151820540600F2B424 /* MockMediaSourcePrivate.h in Headers */, > 07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */, >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >index 0c725f9809d6be97393ccb33dff7d81916598f9d..61ff0eaae564904723c4cb7002f55b4fe48d2999 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >@@ -88,13 +88,14 @@ public: > using DevicesChangedObserverToken = unsigned; > DevicesChangedObserverToken addDevicesChangedObserver(std::function<void()>&&); > void removeDevicesChangedObserver(DevicesChangedObserverToken); >- void captureDevicesChanged(); > > void setVideoCapturePageState(bool, bool); > > protected: > RealtimeMediaSourceCenter(); > >+ void captureDevicesChanged(); >+ > static RealtimeMediaSourceCenter& platformCenter(); > RealtimeMediaSourceSupportedConstraints m_supportedConstraints; > >diff --git a/Source/WebCore/platform/mock/MockMediaDevice.h b/Source/WebCore/platform/mock/MockMediaDevice.h >new file mode 100644 >index 0000000000000000000000000000000000000000..882dbaf10e7d6ada06656ce1871cd20ea5b84e4a >--- /dev/null >+++ b/Source/WebCore/platform/mock/MockMediaDevice.h >@@ -0,0 +1,187 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer >+ * in the documentation and/or other materials provided with the >+ * distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(MEDIA_STREAM) >+ >+#include "CaptureDevice.h" >+#include "RealtimeMediaSource.h" >+ >+namespace WebCore { >+ >+struct MockMicrophoneProperties { >+ template<class Encoder> >+ void encode(Encoder& encoder) const >+ { >+ encoder << static_cast<int32_t>(defaultSampleRate); >+ } >+ >+ template <class Decoder> >+ static std::optional<MockMicrophoneProperties> decode(Decoder& decoder) >+ { >+ std::optional<int32_t> defaultSampleRate; >+ decoder >> defaultSampleRate; >+ if (!defaultSampleRate) >+ return std::nullopt; >+ return MockMicrophoneProperties { *defaultSampleRate }; >+ } >+ >+ int defaultSampleRate { 44100 }; >+}; >+ >+// FIXME: Add support for other properties and serialization of colors. >+struct MockCameraProperties { >+ template<class Encoder> >+ void encode(Encoder& encoder) const >+ { >+ encoder << defaultFrameRate; >+ encoder << facingModeCapability; >+ } >+ >+ template <class Decoder> >+ static std::optional<MockCameraProperties> decode(Decoder& decoder) >+ { >+ std::optional<double> defaultFrameRate; >+ decoder >> defaultFrameRate; >+ if (!defaultFrameRate) >+ return std::nullopt; >+ >+ std::optional<RealtimeMediaSourceSettings::VideoFacingMode> facingModeCapability; >+ decoder >> facingModeCapability; >+ if (!facingModeCapability) >+ return std::nullopt; >+ >+ return MockCameraProperties { *defaultFrameRate, *facingModeCapability, Color::black }; >+ } >+ >+ double defaultFrameRate { 30 }; >+ RealtimeMediaSourceSettings::VideoFacingMode facingModeCapability { RealtimeMediaSourceSettings::VideoFacingMode::User }; >+ Color fillColor { Color::black }; >+}; >+ >+struct MockDisplayProperties { >+ template<class Encoder> >+ void encode(Encoder& encoder) const >+ { >+ encoder << defaultFrameRate; >+ } >+ >+ template <class Decoder> >+ static std::optional<MockDisplayProperties> decode(Decoder& decoder) >+ { >+ std::optional<double> defaultFrameRate; >+ decoder >> defaultFrameRate; >+ if (!defaultFrameRate) >+ return std::nullopt; >+ >+ return MockDisplayProperties { *defaultFrameRate, Color::lightGray }; >+ } >+ >+ double defaultFrameRate { 30 }; >+ Color fillColor { Color::lightGray }; >+}; >+ >+struct MockMediaDevice { >+ bool isMicrophone() const { return WTF::holds_alternative<MockMicrophoneProperties>(properties); } >+ bool isCamera() const { return WTF::holds_alternative<MockCameraProperties>(properties); } >+ bool isDisplay() const { return WTF::holds_alternative<MockDisplayProperties>(properties); } >+ >+ CaptureDevice::DeviceType type() const >+ { >+ if (isMicrophone()) >+ return CaptureDevice::DeviceType::Microphone; >+ if (isCamera()) >+ return CaptureDevice::DeviceType::Camera; >+ ASSERT(isDisplay()); >+ return CaptureDevice::DeviceType::Screen; >+ } >+ >+ template<class Encoder> >+ void encode(Encoder& encoder) const >+ { >+ encoder << persistentId; >+ encoder << label; >+ switchOn(properties, [&](const MockMicrophoneProperties& properties) { >+ encoder << (uint8_t)1; >+ encoder << properties; >+ }, [&](const MockCameraProperties& properties) { >+ encoder << (uint8_t)2; >+ encoder << properties; >+ }, [&](const MockDisplayProperties& properties) { >+ encoder << (uint8_t)3; >+ encoder << properties; >+ }); >+ } >+ >+ template <typename Properties, typename Decoder> >+ static std::optional<MockMediaDevice> decodeMockMediaDevice(Decoder& decoder, String&& persistentId, String&& label) >+ { >+ std::optional<Properties> properties; >+ decoder >> properties; >+ if (!properties) >+ return std::nullopt; >+ return MockMediaDevice { WTFMove(persistentId), WTFMove(label), WTFMove(*properties) }; >+ } >+ >+ template <class Decoder> >+ static std::optional<MockMediaDevice> decode(Decoder& decoder) >+ { >+ std::optional<String> persistentId; >+ decoder >> persistentId; >+ if (!persistentId) >+ return std::nullopt; >+ >+ std::optional<String> label; >+ decoder >> label; >+ if (!label) >+ return std::nullopt; >+ >+ std::optional<uint8_t> index; >+ decoder >> index; >+ if (!index) >+ return std::nullopt; >+ >+ switch (*index) { >+ case 1: >+ return decodeMockMediaDevice<MockMicrophoneProperties>(decoder, WTFMove(*persistentId), WTFMove(*label)); >+ case 2: >+ return decodeMockMediaDevice<MockCameraProperties>(decoder, WTFMove(*persistentId), WTFMove(*label)); >+ case 3: >+ return decodeMockMediaDevice<MockDisplayProperties>(decoder, WTFMove(*persistentId), WTFMove(*label)); >+ } >+ return std::nullopt; >+ } >+ >+ String persistentId; >+ String label; >+ Variant<MockMicrophoneProperties, MockCameraProperties, MockDisplayProperties> properties; >+}; >+ >+} // namespace WebCore >+ >+#endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp b/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp >index 9c6024e53a8a00edfe381c3118eac92e58133d7c..002caf31236ecb646bf82441182cb1508746c002 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp >@@ -118,7 +118,7 @@ void MockRealtimeAudioSource::startProducingData() > #endif > > if (!sampleRate()) >- setSampleRate(device() == MockRealtimeMediaSource::MockDevice::Microphone1 ? 44100 : 48000); >+ setSampleRate(WTF::get<MockMicrophoneProperties>(device().properties).defaultSampleRate); > > m_startTime = MonotonicTime::now(); > m_timer.startRepeating(renderInterval()); >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp b/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >index 4644f082d5e684883a851ac1815ce7de7fe2faff..0875497a1efa110453f8e2d6e523dab3617c94af 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >@@ -44,116 +44,163 @@ > > namespace WebCore { > >-struct MockDeviceInfo { >- ASCIILiteral id { ASCIILiteral::null() }; >- CaptureDevice::DeviceType type; >- ASCIILiteral name { ASCIILiteral::null() }; >- MockRealtimeMediaSource::MockDevice device; >-}; >- >-static const HashMap<String, MockDeviceInfo>& deviceMap() >-{ >- static const auto infoMap = makeNeverDestroyed([] { >- static const MockDeviceInfo devices[] = { >- { "239c24b0-2b15-11e3-8224-0800200c9a66"_s, CaptureDevice::DeviceType::Microphone, "Mock audio device 1"_s, MockRealtimeMediaSource::MockDevice::Microphone1 }, >- { "239c24b1-2b15-11e3-8224-0800200c9a66"_s, CaptureDevice::DeviceType::Microphone, "Mock audio device 2"_s, MockRealtimeMediaSource::MockDevice::Microphone2 }, >- >- { "239c24b2-2b15-11e3-8224-0800200c9a66"_s, CaptureDevice::DeviceType::Camera, "Mock video device 1"_s, MockRealtimeMediaSource::MockDevice::Camera1 }, >- { "239c24b3-2b15-11e3-8224-0800200c9a66"_s, CaptureDevice::DeviceType::Camera, "Mock video device 2"_s, MockRealtimeMediaSource::MockDevice::Camera2 }, >- >- { "SCREEN-1"_s, CaptureDevice::DeviceType::Screen, "Mock screen device 1"_s, MockRealtimeMediaSource::MockDevice::Screen1 }, >- { "SCREEN-2"_s, CaptureDevice::DeviceType::Screen, "Mock screen device 2"_s, MockRealtimeMediaSource::MockDevice::Screen2 }, >- }; >- >- HashMap<String, MockDeviceInfo> map; >- for (auto& info : devices) >- map.add(info.id, info); >+static inline Vector<MockMediaDevice> defaultDevices() >+{ >+ return Vector<MockMediaDevice> { >+ MockMediaDevice { "239c24b0-2b15-11e3-8224-0800200c9a66"_s, "Mock audio device 1"_s, MockMicrophoneProperties { 44100 } }, >+ MockMediaDevice { "239c24b1-2b15-11e3-8224-0800200c9a66"_s, "Mock audio device 2"_s, MockMicrophoneProperties { 48000 } }, >+ >+ MockMediaDevice { "239c24b2-2b15-11e3-8224-0800200c9a66"_s, "Mock video device 1"_s, MockCameraProperties { 30, RealtimeMediaSourceSettings::VideoFacingMode::User, Color::black } }, >+ MockMediaDevice { "239c24b3-2b15-11e3-8224-0800200c9a66"_s, "Mock video device 2"_s, MockCameraProperties { 15, RealtimeMediaSourceSettings::VideoFacingMode::Environment, Color::darkGray } }, >+ >+ MockMediaDevice { "SCREEN-1"_s, "Mock screen device 1"_s, MockDisplayProperties { 30, Color::lightGray } }, >+ MockMediaDevice { "SCREEN-2"_s, "Mock screen device 2"_s, MockDisplayProperties { 10, Color::yellow } } >+ }; >+} >+ >+static Vector<MockMediaDevice>& devices() >+{ >+ static auto devices = makeNeverDestroyed([] { >+ return defaultDevices(); >+ }()); >+ return devices; >+} >+ >+static HashMap<String, MockMediaDevice>& deviceMap() >+{ >+ static auto map = makeNeverDestroyed([] { >+ HashMap<String, MockMediaDevice> map; >+ for (auto& device : devices()) >+ map.add(device.persistentId, device); >+ > return map; > }()); >+ return map; >+} >+ >+static inline Vector<CaptureDevice>& deviceListForDevice(const MockMediaDevice& device) >+{ >+ if (device.isMicrophone()) >+ return MockRealtimeAudioSource::audioDevices(); >+ if (device.isCamera()) >+ return MockRealtimeAudioSource::videoDevices(); > >- return infoMap; >+ ASSERT(device.isDisplay()); >+ return MockRealtimeAudioSource::displayDevices(); > } > >-std::optional<CaptureDevice> MockRealtimeMediaSource::captureDeviceWithPersistentID(CaptureDevice::DeviceType type, const String& id) >+void MockRealtimeMediaSource::createCaptureDevice(const MockMediaDevice& device) > { >- ASSERT(!id.isEmpty()); >+ deviceListForDevice(device).append(captureDeviceWithPersistentID(device.type(), device.persistentId).value()); >+} >+ >+void MockRealtimeMediaSource::resetDevices() >+{ >+ setDevices(defaultDevices()); >+} >+ >+void MockRealtimeMediaSource::setDevices(Vector<MockMediaDevice>&& newMockDevices) >+{ >+ audioDevices().clear(); >+ videoDevices().clear(); >+ displayDevices().clear(); > >- auto map = deviceMap(); >- auto it = map.find(id); >- if (it != map.end() && it->value.type == type) { >- auto device = CaptureDevice(it->value.id, it->value.type, it->value.name); >- device.setEnabled(true); >- return WTFMove(device); >+ auto& mockDevices = devices(); >+ mockDevices = WTFMove(newMockDevices); >+ >+ auto& map = deviceMap(); >+ map.clear(); >+ >+ for (const auto& device : mockDevices) { >+ map.add(device.persistentId, device); >+ createCaptureDevice(device); > } >+} > >- return std::nullopt; >+void MockRealtimeMediaSource::addDevice(const MockMediaDevice& device) >+{ >+ devices().append(device); >+ deviceMap().set(device.persistentId, device); >+ createCaptureDevice(device); > } > >-Vector<CaptureDevice>& MockRealtimeMediaSource::audioDevices() >+void MockRealtimeMediaSource::removeDevice(const String& persistentId) > { >- static auto info = makeNeverDestroyed([] { >- Vector<CaptureDevice> vector; >+ auto& map = deviceMap(); >+ auto iterator = map.find(persistentId); >+ if (iterator == map.end()) >+ return; > >- auto captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Microphone, "239c24b0-2b15-11e3-8224-0800200c9a66"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >+ devices().removeFirstMatching([&persistentId](const auto& device) { >+ return device.persistentId == persistentId; >+ }); > >- captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Microphone, "239c24b1-2b15-11e3-8224-0800200c9a66"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >+ deviceListForDevice(iterator->value).removeFirstMatching([&persistentId](const auto& device) { >+ return device.persistentId() == persistentId; >+ }); > >- return vector; >- }()); >- return info; >+ map.remove(iterator); > } > >-Vector<CaptureDevice>& MockRealtimeMediaSource::videoDevices() >+std::optional<CaptureDevice> MockRealtimeMediaSource::captureDeviceWithPersistentID(CaptureDevice::DeviceType type, const String& id) > { >- static auto info = makeNeverDestroyed([] { >- Vector<CaptureDevice> vector; >+ ASSERT(!id.isEmpty()); > >- auto captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Camera, "239c24b2-2b15-11e3-8224-0800200c9a66"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >+ auto& map = deviceMap(); >+ auto iterator = map.find(id); >+ if (iterator == map.end() || iterator->value.type() != type) >+ return std::nullopt; > >- captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Camera, "239c24b3-2b15-11e3-8224-0800200c9a66"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >+ CaptureDevice device { iterator->value.persistentId, type, iterator->value.label }; >+ device.setEnabled(true); >+ return WTFMove(device); >+} >+ >+Vector<CaptureDevice>& MockRealtimeMediaSource::audioDevices() >+{ >+ static auto audioDevices = makeNeverDestroyed([] { >+ Vector<CaptureDevice> audioDevices; >+ for (const auto& device : devices()) { >+ if (device.type() == CaptureDevice::DeviceType::Microphone) >+ audioDevices.append(captureDeviceWithPersistentID(CaptureDevice::DeviceType::Microphone, device.persistentId).value()); >+ } >+ return audioDevices; >+ }()); >+ return audioDevices; >+} > >- return vector; >+Vector<CaptureDevice>& MockRealtimeMediaSource::videoDevices() >+{ >+ static auto videoDevices = makeNeverDestroyed([] { >+ Vector<CaptureDevice> videoDevices; >+ for (const auto& device : devices()) { >+ if (device.type() == CaptureDevice::DeviceType::Camera) >+ videoDevices.append(captureDeviceWithPersistentID(CaptureDevice::DeviceType::Camera, device.persistentId).value()); >+ } >+ return videoDevices; > }()); >- return info; >+ return videoDevices; > } > > Vector<CaptureDevice>& MockRealtimeMediaSource::displayDevices() > { >- static auto devices = makeNeverDestroyed([] { >- Vector<CaptureDevice> vector; >- >- auto captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Screen, "SCREEN-1"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >- >- captureDevice = captureDeviceWithPersistentID(CaptureDevice::DeviceType::Screen, "SCREEN-2"_s); >- ASSERT(captureDevice); >- vector.append(WTFMove(captureDevice.value())); >- >- return vector; >+ static auto displayDevices = makeNeverDestroyed([] { >+ Vector<CaptureDevice> displayDevices; >+ for (const auto& device : devices()) { >+ if (device.type() == CaptureDevice::DeviceType::Screen) >+ displayDevices.append(captureDeviceWithPersistentID(CaptureDevice::DeviceType::Screen, device.persistentId).value()); >+ } >+ return displayDevices; > }()); > >- return devices; >+ return displayDevices; > } > > MockRealtimeMediaSource::MockRealtimeMediaSource(const String& id, RealtimeMediaSource::Type type, const String& name) > : RealtimeMediaSource(id, type, name) >+ , m_device(deviceMap().get(id)) > { > ASSERT(type != RealtimeMediaSource::Type::None); >- >- auto map = deviceMap(); >- auto it = map.find(id); >- ASSERT(it != map.end()); >- >- m_device = it->value.device; > setPersistentID(String(id)); > } > >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSource.h b/Source/WebCore/platform/mock/MockRealtimeMediaSource.h >index a1d3e9b61b6113365a784300283b94a5e11fa75f..3355da661ec60e9df1a251c000ab56971cf8cb1c 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSource.h >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSource.h >@@ -32,27 +32,32 @@ > > #if ENABLE(MEDIA_STREAM) > >+#include "CaptureDevice.h" >+#include "MockMediaDevice.h" > #include "RealtimeMediaSource.h" > > namespace WebCore { > >-class CaptureDevice; >- > class MockRealtimeMediaSource : public RealtimeMediaSource { > public: > virtual ~MockRealtimeMediaSource() = default; > >+ static void setDevices(Vector<MockMediaDevice>&&); >+ static void addDevice(const MockMediaDevice&); >+ static void removeDevice(const String& persistentId); >+ WEBCORE_EXPORT static void resetDevices(); >+ > static Vector<CaptureDevice>& audioDevices(); > static Vector<CaptureDevice>& videoDevices(); > static Vector<CaptureDevice>& displayDevices(); > > static std::optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&); > >- enum class MockDevice { Invalid, Microphone1, Microphone2, Camera1, Camera2, Screen1, Screen2 }; >- > protected: > MockRealtimeMediaSource(const String& id, Type, const String& name); > >+ static void createCaptureDevice(const MockMediaDevice&); >+ > virtual void updateSettings(RealtimeMediaSourceSettings&) = 0; > virtual void initializeCapabilities(RealtimeMediaSourceCapabilities&) = 0; > virtual void initializeSupportedConstraints(RealtimeMediaSourceSupportedConstraints&) = 0; >@@ -62,8 +67,8 @@ protected: > > RealtimeMediaSourceSupportedConstraints& supportedConstraints(); > >- MockDevice device() const { return m_device; } >- MockDevice m_device { MockDevice::Invalid }; >+ const MockMediaDevice& device() const { return m_device; } >+ MockMediaDevice m_device; > > private: > void initializeCapabilities(); >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >index 77a0f8edd3cb7f6ae233b750301215368200701c..df91ebe0fe8544114a662c76e42afca7a700edac 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >@@ -37,16 +37,39 @@ > > namespace WebCore { > >-void MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(bool enabled) >+MockRealtimeMediaSourceCenter& MockRealtimeMediaSourceCenter::singleton() > { > static NeverDestroyed<MockRealtimeMediaSourceCenter> center; >+ return center; >+} >+ >+void MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(bool enabled) >+{ > static bool active = false; > if (active != enabled) { > active = enabled; >- RealtimeMediaSourceCenter::setSharedStreamCenterOverride(enabled ? ¢er.get() : nullptr); >+ RealtimeMediaSourceCenter::setSharedStreamCenterOverride(enabled ? &singleton() : nullptr); > } > } > >+void MockRealtimeMediaSourceCenter::setDevices(Vector<MockMediaDevice>&& newMockDevices) >+{ >+ MockRealtimeMediaSource::setDevices(WTFMove(newMockDevices)); >+ singleton().captureDevicesChanged(); >+} >+ >+void MockRealtimeMediaSourceCenter::addDevice(const MockMediaDevice& device) >+{ >+ MockRealtimeMediaSource::addDevice(device); >+ singleton().captureDevicesChanged(); >+} >+ >+void MockRealtimeMediaSourceCenter::removeDevice(const String& persistentId) >+{ >+ MockRealtimeMediaSource::removeDevice(persistentId); >+ singleton().captureDevicesChanged(); >+} >+ > } // namespace WebCore > > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h >index 0f92f9d43f989ba6e8c3aa8f35c404eb8b429f3f..be47a0e3e46211d4effed02c1d716579a1c45752 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h >@@ -39,6 +39,10 @@ class MockRealtimeMediaSourceCenter final : public RealtimeMediaSourceCenter { > public: > WEBCORE_EXPORT static void setMockRealtimeMediaSourceCenterEnabled(bool); > >+ WEBCORE_EXPORT static void setDevices(Vector<MockMediaDevice>&&); >+ WEBCORE_EXPORT static void addDevice(const MockMediaDevice&); >+ WEBCORE_EXPORT static void removeDevice(const String& persistentId); >+ > static RealtimeMediaSource::VideoCaptureFactory& videoCaptureSourceFactory() { return MockRealtimeVideoSource::factory(); } > static RealtimeMediaSource::AudioCaptureFactory& audioCaptureSourceFactory() { return MockRealtimeAudioSource::factory(); } > >@@ -46,6 +50,8 @@ private: > MockRealtimeMediaSourceCenter() = default; > friend NeverDestroyed<MockRealtimeMediaSourceCenter>; > >+ static MockRealtimeMediaSourceCenter& singleton(); >+ > RealtimeMediaSource::AudioCaptureFactory& audioFactory() final { return MockRealtimeAudioSource::factory(); } > RealtimeMediaSource::VideoCaptureFactory& videoFactory() final { return MockRealtimeVideoSource::factory(); } > >diff --git a/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp b/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp >index 03a7c3ec2f10396075e1177bb0545db7c5d83687..9c41e1c4727ee416643227ab0e4a53c9bcc9b200 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp >@@ -108,31 +108,18 @@ MockRealtimeVideoSource::MockRealtimeVideoSource(const String& deviceID, const S > : MockRealtimeMediaSource(deviceID, RealtimeMediaSource::Type::Video, name) > , m_timer(RunLoop::current(), this, &MockRealtimeVideoSource::generateFrame) > { >- switch (device()) { >- case MockDevice::Camera1: >- setFrameRate(30); >- setFacingMode(RealtimeMediaSourceSettings::User); >- break; >- case MockDevice::Camera2: >- setFrameRate(15); >- setFacingMode(RealtimeMediaSourceSettings::Environment); >- break; >- case MockDevice::Screen1: >- setFrameRate(30); >- break; >- case MockDevice::Screen2: >- setFrameRate(10); >- break; >- case MockDevice::Microphone1: >- case MockDevice::Microphone2: >- case MockDevice::Invalid: >- ASSERT_NOT_REACHED(); >- break; >- } >- > m_dashWidths.reserveInitialCapacity(2); > m_dashWidths.uncheckedAppend(6); > m_dashWidths.uncheckedAppend(6); >+ >+ if (mockScreen()) { >+ setFrameRate(WTF::get<MockDisplayProperties>(device().properties).defaultFrameRate); >+ return; >+ } >+ >+ auto& properties = WTF::get<MockCameraProperties>(device().properties); >+ setFrameRate(properties.defaultFrameRate); >+ setFacingMode(properties.facingModeCapability); > } > > MockRealtimeVideoSource::~MockRealtimeVideoSource() >@@ -191,10 +178,7 @@ void MockRealtimeVideoSource::updateSettings(RealtimeMediaSourceSettings& settin > void MockRealtimeVideoSource::initializeCapabilities(RealtimeMediaSourceCapabilities& capabilities) > { > if (mockCamera()) { >- if (device() == MockDevice::Camera1) >- capabilities.addFacingMode(RealtimeMediaSourceSettings::User); >- else >- capabilities.addFacingMode(RealtimeMediaSourceSettings::Environment); >+ capabilities.addFacingMode(WTF::get<MockCameraProperties>(device().properties).facingModeCapability); > > capabilities.setWidth(CapabilityValueOrRange(320, 1920)); > capabilities.setHeight(CapabilityValueOrRange(240, 1080)); >@@ -392,7 +376,7 @@ void MockRealtimeVideoSource::drawText(GraphicsContext& context) > context.drawText(statsFont, TextRun((StringView(string))), statsLocation); > } else { > statsLocation.move(0, m_statsFontSize); >- context.drawText(statsFont, TextRun((StringView(device() == MockDevice::Screen1 ? "Screen 1" : "Screen 2"))), statsLocation); >+ context.drawText(statsFont, TextRun { id() }, statsLocation); > } > > FloatPoint bipBopLocation(size.width() * .6, size.height() * .6); >@@ -431,27 +415,7 @@ void MockRealtimeVideoSource::generateFrame() > auto& size = this->size(); > FloatRect frameRect(FloatPoint(), size); > >- Color fillColor; >- switch (device()) { >- case MockDevice::Camera1: >- fillColor = Color::black; >- break; >- case MockDevice::Camera2: >- fillColor = Color::darkGray; >- break; >- case MockDevice::Screen1: >- fillColor = Color::lightGray; >- break; >- case MockDevice::Screen2: >- fillColor = Color::yellow; >- break; >- case MockDevice::Microphone1: >- case MockDevice::Microphone2: >- case MockDevice::Invalid: >- ASSERT_NOT_REACHED(); >- break; >- } >- >+ auto fillColor = mockCamera() ? WTF::get<MockCameraProperties>(device().properties).fillColor : WTF::get<MockDisplayProperties>(device().properties).fillColor; > context.fillRect(FloatRect(FloatPoint(), size), fillColor); > > if (!muted()) { >diff --git a/Source/WebCore/platform/mock/MockRealtimeVideoSource.h b/Source/WebCore/platform/mock/MockRealtimeVideoSource.h >index bd526826ff0482b44fc49a4c8607b6668094cf47..a6589b875487704e8b4887a452ee37d97710a60d 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeVideoSource.h >+++ b/Source/WebCore/platform/mock/MockRealtimeVideoSource.h >@@ -83,8 +83,8 @@ private: > > void delaySamples(Seconds) override; > >- bool mockCamera() const { return device() == MockDevice::Camera1 || device() == MockDevice::Camera2; } >- bool mockScreen() const { return device() == MockDevice::Screen1 || device() == MockDevice::Screen2; } >+ bool mockCamera() const { return WTF::holds_alternative<MockCameraProperties>(device().properties); } >+ bool mockScreen() const { return WTF::holds_alternative<MockDisplayProperties>(device().properties); } > > float m_baseFontSize { 0 }; > float m_bipBopFontSize { 0 }; >diff --git a/Source/WebKit/CMakeLists.txt b/Source/WebKit/CMakeLists.txt >index bd9de34ed2bff930a6dc30a0e4c737908887f210..422e5242d69e23bf11df69d978329c571b08a186 100644 >--- a/Source/WebKit/CMakeLists.txt >+++ b/Source/WebKit/CMakeLists.txt >@@ -402,6 +402,7 @@ set(WebKit_SOURCES > UIProcess/API/C/WKInspector.cpp > UIProcess/API/C/WKKeyValueStorageManager.cpp > UIProcess/API/C/WKMediaSessionMetadata.cpp >+ UIProcess/API/C/WKMockMediaDevice.cpp > UIProcess/API/C/WKNavigationActionRef.cpp > UIProcess/API/C/WKNavigationDataRef.cpp > UIProcess/API/C/WKNavigationRef.cpp >diff --git a/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.cpp b/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..b9356e5dc1a8dc8c26247e8fe6ed570c83c3a066 >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.cpp >@@ -0,0 +1,66 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * >+ */ >+ >+#include "config.h" >+#include "WKMockMediaDevice.h" >+ >+#include "WKAPICast.h" >+#include "WKString.h" >+#include "WebProcessPool.h" >+#include <WebCore/MockMediaDevice.h> >+ >+using namespace WebKit; >+ >+void WKAddMockMediaDevice(WKContextRef context, WKStringRef persistentId, WKStringRef label, WKStringRef type) >+{ >+#if ENABLE(MEDIA_STREAM) >+ String typeString = WebKit::toImpl(persistentId)->string(); >+ Variant<WebCore::MockMicrophoneProperties, WebCore::MockCameraProperties, WebCore::MockDisplayProperties> properties; >+ if (typeString == "camera") >+ properties = WebCore::MockCameraProperties { }; >+ if (typeString == "screen") >+ properties = WebCore::MockDisplayProperties { }; >+ if (typeString != "microphone") >+ return; >+ >+ toImpl(context)->addMockMediaDevice({ WebKit::toImpl(persistentId)->string(), WebKit::toImpl(label)->string(), WTFMove(properties) }); >+#endif >+} >+ >+void WKClearMockMediaDevices(WKContextRef context) >+{ >+ toImpl(context)->clearMockMediaDevices(); >+} >+ >+void WKRemoveMockMediaDevice(WKContextRef context, WKStringRef persistentId) >+{ >+ toImpl(context)->removeMockMediaDevice(WebKit::toImpl(persistentId)->string()); >+} >+ >+void WKResetMockMediaDevices(WKContextRef context) >+{ >+ toImpl(context)->resetMockMediaDevices(); >+} >diff --git a/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.h b/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.h >new file mode 100644 >index 0000000000000000000000000000000000000000..f776d281711949a10ec70d421cab6a035b074a1a >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/C/WKMockMediaDevice.h >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * >+ */ >+ >+#pragma once >+ >+#include <WebKit/WKBase.h> >+ >+#ifdef __cplusplus >+extern "C" { >+#endif >+ >+WK_EXPORT void WKAddMockMediaDevice(WKContextRef, WKStringRef persistentId, WKStringRef label, WKStringRef type); >+WK_EXPORT void WKClearMockMediaDevices(WKContextRef); >+WK_EXPORT void WKRemoveMockMediaDevice(WKContextRef, WKStringRef persistentId); >+WK_EXPORT void WKResetMockMediaDevices(WKContextRef); >+ >+#ifdef __cplusplus >+} >+#endif >diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp >index bd377e46b671b739ef7c064089dedca8da4a0a64..72a83df810af37cce4937ff5bf478c66c1b0d7ae 100644 >--- a/Source/WebKit/UIProcess/WebProcessPool.cpp >+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp >@@ -82,6 +82,7 @@ > #include <JavaScriptCore/JSCInlines.h> > #include <WebCore/ApplicationCacheStorage.h> > #include <WebCore/LogInitialization.h> >+#include <WebCore/MockRealtimeMediaSourceCenter.h> > #include <WebCore/NetworkStorageSession.h> > #include <WebCore/PlatformScreen.h> > #include <WebCore/Process.h> >@@ -2212,4 +2213,36 @@ void WebProcessPool::unregisterSuspendedPageProxy(SuspendedPageProxy& page) > m_suspendedPages.remove(iterator); > } > >+void WebProcessPool::addMockMediaDevice(const MockMediaDevice& device) >+{ >+#if ENABLE(MEDIA_STREAM) >+ MockRealtimeMediaSourceCenter::addDevice(device); >+ sendToAllProcesses(Messages::WebProcess::AddMockMediaDevice { device }); >+#endif >+} >+ >+void WebProcessPool::clearMockMediaDevices() >+{ >+#if ENABLE(MEDIA_STREAM) >+ MockRealtimeMediaSourceCenter::setDevices({ }); >+ sendToAllProcesses(Messages::WebProcess::ClearMockMediaDevices { }); >+#endif >+} >+ >+void WebProcessPool::removeMockMediaDevice(const String& persistentId) >+{ >+#if ENABLE(MEDIA_STREAM) >+ MockRealtimeMediaSourceCenter::removeDevice(persistentId); >+ sendToAllProcesses(Messages::WebProcess::RemoveMockMediaDevice { persistentId }); >+#endif >+} >+ >+void WebProcessPool::resetMockMediaDevices() >+{ >+#if ENABLE(MEDIA_STREAM) >+ MockRealtimeMediaSource::resetDevices(); >+ sendToAllProcesses(Messages::WebProcess::ResetMockMediaDevices { }); >+#endif >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h >index aeb1910a60e45af0255c05e7edccbbdb1693b8f0..83b063e9e5df516c0dadfefd3b92bc549a17244a 100644 >--- a/Source/WebKit/UIProcess/WebProcessPool.h >+++ b/Source/WebKit/UIProcess/WebProcessPool.h >@@ -82,6 +82,10 @@ class Navigation; > class PageConfiguration; > } > >+namespace WebCore { >+struct MockMediaDevice; >+} >+ > namespace WebKit { > > class DownloadProxy; >@@ -454,6 +458,11 @@ public: > > void screenPropertiesStateChanged(); > >+ void addMockMediaDevice(const WebCore::MockMediaDevice&); >+ void clearMockMediaDevices(); >+ void removeMockMediaDevice(const String& persistentId); >+ void resetMockMediaDevices(); >+ > private: > void platformInitialize(); > >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index 6a50721ee229997a95726eab07e9182652cdf2a5..0863f995885cbe962243d26a94efcf1775b7f566 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -913,6 +913,8 @@ > 410482CE1DDD324F00F006D0 /* RTCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 410482CC1DDD2FB500F006D0 /* RTCNetwork.h */; }; > 4112B5551FA0EA7A00E67875 /* NetworkRTCResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4112B5471F9FD3AB00E67875 /* NetworkRTCResolver.cpp */; }; > 4112B5551FA0EA7A00E67986 /* NetworkRTCResolverCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4112B5471F9FD3AB00E67986 /* NetworkRTCResolverCocoa.cpp */; }; >+ 411A8DDB20DDD1AC0060D34F /* WKMockMediaDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 411A8DD920DDB6050060D34F /* WKMockMediaDevice.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 411A8DDC20DDD23F0060D34F /* WKMockMediaDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 411A8DDA20DDB6050060D34F /* WKMockMediaDevice.cpp */; }; > 411B22641E371BA6004F7363 /* LibWebRTCNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 411B22621E371244004F7363 /* LibWebRTCNetwork.h */; }; > 413075A91DE85F2C0039EC69 /* NetworkRTCSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413075981DE84FB00039EC69 /* NetworkRTCSocket.cpp */; }; > 413075AA1DE85F300039EC69 /* NetworkRTCMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4130759A1DE84FB00039EC69 /* NetworkRTCMonitor.cpp */; }; >@@ -3299,6 +3301,8 @@ > 4112B5471F9FD3AB00E67986 /* NetworkRTCResolverCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkRTCResolverCocoa.cpp; path = NetworkProcess/webrtc/NetworkRTCResolverCocoa.cpp; sourceTree = "<group>"; }; > 4112B5481F9FD3AC00E67875 /* NetworkRTCResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkRTCResolver.h; path = NetworkProcess/webrtc/NetworkRTCResolver.h; sourceTree = "<group>"; }; > 4112B5481F9FD3AC00E67986 /* NetworkRTCResolverCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkRTCResolverCocoa.h; path = NetworkProcess/webrtc/NetworkRTCResolverCocoa.h; sourceTree = "<group>"; }; >+ 411A8DD920DDB6050060D34F /* WKMockMediaDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMockMediaDevice.h; sourceTree = "<group>"; }; >+ 411A8DDA20DDB6050060D34F /* WKMockMediaDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKMockMediaDevice.cpp; sourceTree = "<group>"; }; > 411B22621E371244004F7363 /* LibWebRTCNetwork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCNetwork.h; path = Network/webrtc/LibWebRTCNetwork.h; sourceTree = "<group>"; }; > 413075981DE84FB00039EC69 /* NetworkRTCSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkRTCSocket.cpp; path = NetworkProcess/webrtc/NetworkRTCSocket.cpp; sourceTree = "<group>"; }; > 413075991DE84FB00039EC69 /* NetworkRTCSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkRTCSocket.h; path = NetworkProcess/webrtc/NetworkRTCSocket.h; sourceTree = "<group>"; }; >@@ -7572,6 +7576,8 @@ > C98C48A81B6FD5B500145103 /* WKMediaSessionFocusManager.h */, > C9CD43991B4B024200239E33 /* WKMediaSessionMetadata.cpp */, > C9CD439A1B4B024200239E33 /* WKMediaSessionMetadata.h */, >+ 411A8DDA20DDB6050060D34F /* WKMockMediaDevice.cpp */, >+ 411A8DD920DDB6050060D34F /* WKMockMediaDevice.h */, > C09AE5E8125257C20025825D /* WKNativeEvent.h */, > 2D3A65D81A7C3A1F00CAC637 /* WKNavigationActionRef.cpp */, > 2D3A65D91A7C3A1F00CAC637 /* WKNavigationActionRef.h */, >@@ -9643,6 +9649,7 @@ > C98C48AA1B6FD5B500145103 /* WKMediaSessionFocusManager.h in Headers */, > C9CD439D1B4B024F00239E33 /* WKMediaSessionMetadata.h in Headers */, > 1AB40EE61BF677E300BA81BE /* WKMenuItemIdentifiersPrivate.h in Headers */, >+ 411A8DDB20DDD1AC0060D34F /* WKMockMediaDevice.h in Headers */, > BC4075FE124FF0270068F20A /* WKMutableArray.h in Headers */, > BC407600124FF0270068F20A /* WKMutableDictionary.h in Headers */, > C09AE5E9125257C20025825D /* WKNativeEvent.h in Headers */, >@@ -10358,13 +10365,9 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > ); > name = "Unlock keychain"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -10376,13 +10379,9 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > ); > name = "Unlock keychain"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -10394,13 +10393,9 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > ); > name = "Remove stale entitlement file"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -10412,13 +10407,9 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > ); > name = "Remove stale entitlement file"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -10430,14 +10421,10 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > "$(TEMP_FILE_DIR)/$(FULL_PRODUCT_NAME).xcent", > ); > name = "Process WebContent entitlements"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -10449,14 +10436,10 @@ > buildActionMask = 2147483647; > files = ( > ); >- inputFileListPaths = ( >- ); > inputPaths = ( > "$(TEMP_FILE_DIR)/$(FULL_PRODUCT_NAME).xcent", > ); > name = "Process WebContent entitlements"; >- outputFileListPaths = ( >- ); > outputPaths = ( > ); > runOnlyForDeploymentPostprocessing = 0; >@@ -11465,6 +11448,7 @@ > C98C48A91B6FD5B500145103 /* WKMediaSessionFocusManager.cpp in Sources */, > C9CD439E1B4B025300239E33 /* WKMediaSessionMetadata.cpp in Sources */, > 1AB40EE51BF677E300BA81BE /* WKMenuItemIdentifiers.mm in Sources */, >+ 411A8DDC20DDD23F0060D34F /* WKMockMediaDevice.cpp in Sources */, > BC4075FD124FF0270068F20A /* WKMutableArray.cpp in Sources */, > BC4075FF124FF0270068F20A /* WKMutableDictionary.cpp in Sources */, > 1A5B1C501898606F004FCF9B /* WKNavigation.mm in Sources */, >diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp >index 8fa86ad2634216833021558f476f7e00bea04612..0066f113699644d66e278e3ef3d29e8142e500fa 100644 >--- a/Source/WebKit/WebProcess/WebProcess.cpp >+++ b/Source/WebKit/WebProcess/WebProcess.cpp >@@ -101,6 +101,7 @@ > #include <WebCore/MemoryCache.h> > #include <WebCore/MemoryRelease.h> > #include <WebCore/MessagePort.h> >+#include <WebCore/MockRealtimeMediaSourceCenter.h> > #include <WebCore/NetworkStorageSession.h> > #include <WebCore/Page.h> > #include <WebCore/PageCache.h> >@@ -1690,4 +1691,26 @@ void WebProcess::setScreenProperties(const WebCore::ScreenProperties& properties > } > #endif > >+#if ENABLE(MEDIA_STREAM) >+void WebProcess::addMockMediaDevice(const WebCore::MockMediaDevice& device) >+{ >+ MockRealtimeMediaSourceCenter::addDevice(device); >+} >+ >+void WebProcess::clearMockMediaDevices() >+{ >+ MockRealtimeMediaSourceCenter::setDevices({ }); >+} >+ >+void WebProcess::removeMockMediaDevice(const String& persistentId) >+{ >+ MockRealtimeMediaSourceCenter::removeDevice(persistentId); >+} >+ >+void WebProcess::resetMockMediaDevices() >+{ >+ MockRealtimeMediaSource::resetDevices(); >+} >+#endif >+ > } // namespace WebKit >diff --git a/Source/WebKit/WebProcess/WebProcess.h b/Source/WebKit/WebProcess/WebProcess.h >index b8520acd2bd83c4915713fd54340efeb456dcefb..88cc21f9f510980b006f5ce782628435af6ac26b 100644 >--- a/Source/WebKit/WebProcess/WebProcess.h >+++ b/Source/WebKit/WebProcess/WebProcess.h >@@ -69,6 +69,7 @@ class ResourceRequest; > class UserGestureToken; > struct MessagePortIdentifier; > struct MessageWithMessagePorts; >+struct MockMediaDevice; > struct PluginInfo; > struct SecurityOriginData; > struct SoupNetworkProxySettings; >@@ -359,6 +360,13 @@ private: > void stopRunLoop() override; > #endif > >+#if ENABLE(MEDIA_STREAM) >+ void addMockMediaDevice(const WebCore::MockMediaDevice&); >+ void clearMockMediaDevices(); >+ void removeMockMediaDevice(const String& persistentId); >+ void resetMockMediaDevices(); >+#endif >+ > void platformInitializeProcess(const ChildProcessInitializationParameters&); > > // IPC::Connection::Client >diff --git a/Source/WebKit/WebProcess/WebProcess.messages.in b/Source/WebKit/WebProcess/WebProcess.messages.in >index 5ab522be391348811b6daa37c793c9a0c4f79827..0db8bd943beed8353292c90cdc18ea6c27c1505a 100644 >--- a/Source/WebKit/WebProcess/WebProcess.messages.in >+++ b/Source/WebKit/WebProcess/WebProcess.messages.in >@@ -139,4 +139,11 @@ messages -> WebProcess LegacyReceiver { > #if PLATFORM(COCOA) > SetMediaMIMETypes(Vector<String> types) > #endif >+ >+#if ENABLE(MEDIA_STREAM) >+ AddMockMediaDevice(struct WebCore::MockMediaDevice device); >+ ClearMockMediaDevices(); >+ RemoveMockMediaDevice(String persistentId); >+ ResetMockMediaDevices(); >+#endif > } >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index ce05f7f388a51f44c17d08b4f986e14549219dfd..b98477e747371f170278f96002358f291e48e03e 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,31 @@ >+2018-06-25 Youenn Fablet <youenn@apple.com> >+ >+ Add API to control mock media devices >+ https://bugs.webkit.org/show_bug.cgi?id=186958 >+ >+ Reviewed by Eric Carlson. >+ >+ Add test runner API to clear/add/remove/reset mock media devices. >+ >+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: >+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp: >+ (WTR::TestRunner::addMockMediaDevice): >+ (WTR::TestRunner::addMockCameraDevice): >+ (WTR::TestRunner::addMockMicrophoneDevice): >+ (WTR::TestRunner::addMockScreenDevice): >+ (WTR::TestRunner::clearMockMediaDevices): >+ (WTR::TestRunner::removeMockMediaDevice): >+ (WTR::TestRunner::resetMockMediaDevices): >+ * WebKitTestRunner/InjectedBundle/TestRunner.h: >+ * WebKitTestRunner/TestController.cpp: >+ (WTR::TestController::addMockMediaDevice): >+ (WTR::TestController::clearMockMediaDevices): >+ (WTR::TestController::removeMockMediaDevice): >+ (WTR::TestController::resetMockMediaDevices): >+ * WebKitTestRunner/TestController.h: >+ * WebKitTestRunner/TestInvocation.cpp: >+ (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle): >+ > 2018-06-25 Ross Kirsling <ross.kirsling@sony.com> > > [WinCairo] Unreviewed build fix for r233088. >diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >index 7e7659cc3bffce0aa876dddc9f02d04976a3db9f..1791668127a6660772ca191c05839d6cc08f3964 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >@@ -336,4 +336,11 @@ interface TestRunner { > void getApplicationManifestThen(object callback); > > void installFakeHelvetica(DOMString configuration); >+ >+ void addMockCameraDevice(DOMString persistentId, DOMString label); >+ void addMockMicrophoneDevice(DOMString persistentId, DOMString label); >+ void addMockScreenDevice(DOMString persistentId, DOMString label); >+ void clearMockMediaDevices(); >+ void removeMockMediaDevice(DOMString persistentId); >+ void resetMockMediaDevices(); > }; >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >index 2831a87b97150279853401943ddc4f9f32a63cc2..95aaef4cda0f88c28a1df8e3efa2c551ea7b73d8 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >@@ -1971,6 +1971,71 @@ void TestRunner::callDidReceiveAllStorageAccessEntriesCallback(Vector<String>& d > callTestRunnerCallback(AllStorageAccessEntriesCallbackID, 1, &result); > } > >+void TestRunner::addMockMediaDevice(JSStringRef persistentId, JSStringRef label, const char* type) >+{ >+ Vector<WKRetainPtr<WKStringRef>> keys; >+ Vector<WKRetainPtr<WKTypeRef>> values; >+ >+ keys.append({ AdoptWK, WKStringCreateWithUTF8CString("PersistentID") }); >+ values.append(toWK(persistentId)); >+ >+ keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Label") }); >+ values.append(toWK(label)); >+ >+ keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Type") }); >+ values.append({ AdoptWK, WKStringCreateWithUTF8CString(type) }); >+ >+ Vector<WKStringRef> rawKeys; >+ Vector<WKTypeRef> rawValues; >+ rawKeys.resize(keys.size()); >+ rawValues.resize(values.size()); >+ >+ for (size_t i = 0; i < keys.size(); ++i) { >+ rawKeys[i] = keys[i].get(); >+ rawValues[i] = values[i].get(); >+ } >+ >+ WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("AddMockMediaDevice")); >+ WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); >+ >+ WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); >+} >+ >+void TestRunner::addMockCameraDevice(JSStringRef persistentId, JSStringRef label) >+{ >+ addMockMediaDevice(persistentId, label, "camera"); >+} >+ >+void TestRunner::addMockMicrophoneDevice(JSStringRef persistentId, JSStringRef label) >+{ >+ addMockMediaDevice(persistentId, label, "microphone"); >+} >+ >+void TestRunner::addMockScreenDevice(JSStringRef persistentId, JSStringRef label) >+{ >+ addMockMediaDevice(persistentId, label, "screen"); >+} >+ >+void TestRunner::clearMockMediaDevices() >+{ >+ WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearMockMediaDevices")); >+ WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr); >+} >+ >+void TestRunner::removeMockMediaDevice(JSStringRef persistentId) >+{ >+ WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveMockMediaDevice")); >+ WKRetainPtr<WKTypeRef> messageBody(toWK(persistentId)); >+ >+ WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); >+} >+ >+void TestRunner::resetMockMediaDevices() >+{ >+ WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ResetMockMediaDevices")); >+ WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr); >+} >+ > #if PLATFORM(MAC) > void TestRunner::connectMockGamepad(unsigned index) > { >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >index f2901bc62e6210f4071f287a432efb17eb3c9d69..789ba2302368309ca099a1efb7457e17a25326f2 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >@@ -446,6 +446,13 @@ public: > void dumpAllHTTPRedirectedResponseHeaders() { m_dumpAllHTTPRedirectedResponseHeaders = true; } > bool shouldDumpAllHTTPRedirectedResponseHeaders() const { return m_dumpAllHTTPRedirectedResponseHeaders; } > >+ void addMockCameraDevice(JSStringRef persistentId, JSStringRef label); >+ void addMockMicrophoneDevice(JSStringRef persistentId, JSStringRef label); >+ void addMockScreenDevice(JSStringRef persistentId, JSStringRef label); >+ void clearMockMediaDevices(); >+ void removeMockMediaDevice(JSStringRef persistentId); >+ void resetMockMediaDevices(); >+ > private: > TestRunner(); > >@@ -455,6 +462,8 @@ private: > void setDumpPixels(bool); > void setWaitUntilDone(bool); > >+ void addMockMediaDevice(JSStringRef persistentId, JSStringRef label, const char* type); >+ > WKRetainPtr<WKURLRef> m_testURL; // Set by InjectedBundlePage once provisional load starts. > > bool m_shouldDumpAllFrameScrollPositions; >diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp >index ba85189549dd37509eb3e00e8373816e380f3c3a..377ccfe2c3e6096edbaaefc2afa7648d03de7648 100644 >--- a/Tools/WebKitTestRunner/TestController.cpp >+++ b/Tools/WebKitTestRunner/TestController.cpp >@@ -43,6 +43,7 @@ > #include <WebKit/WKFrameHandleRef.h> > #include <WebKit/WKFrameInfoRef.h> > #include <WebKit/WKIconDatabase.h> >+#include <WebKit/WKMockMediaDevice.h> > #include <WebKit/WKNavigationResponseRef.h> > #include <WebKit/WKNotification.h> > #include <WebKit/WKNotificationManager.h> >@@ -2866,6 +2867,26 @@ void TestController::statisticsResetToConsistentState() > WKWebsiteDataStoreStatisticsResetToConsistentState(dataStore); > } > >+void TestController::addMockMediaDevice(WKStringRef persistentID, WKStringRef label, WKStringRef type) >+{ >+ WKAddMockMediaDevice(platformContext(), persistentID, label, type); >+} >+ >+void TestController::clearMockMediaDevices() >+{ >+ WKClearMockMediaDevices(platformContext()); >+} >+ >+void TestController::removeMockMediaDevice(WKStringRef persistentID) >+{ >+ WKRemoveMockMediaDevice(platformContext(), persistentID); >+} >+ >+void TestController::resetMockMediaDevices() >+{ >+ WKResetMockMediaDevices(platformContext()); >+} >+ > #if !PLATFORM(COCOA) > void TestController::platformAddTestOptions(TestOptions&) const > { >diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h >index f33783443ef62ab0cddf8898aae0767adde1cb21..a48103fad7a538605f99172eda2cd1059c17448e 100644 >--- a/Tools/WebKitTestRunner/TestController.h >+++ b/Tools/WebKitTestRunner/TestController.h >@@ -213,6 +213,11 @@ public: > bool didReceiveServerRedirectForProvisionalNavigation() const { return m_didReceiveServerRedirectForProvisionalNavigation; } > void clearDidReceiveServerRedirectForProvisionalNavigation() { m_didReceiveServerRedirectForProvisionalNavigation = false; } > >+ void addMockMediaDevice(WKStringRef persistentID, WKStringRef label, WKStringRef type); >+ void clearMockMediaDevices(); >+ void removeMockMediaDevice(WKStringRef persistentID); >+ void resetMockMediaDevices(); >+ > private: > WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef); > WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration() const; >diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp >index 52475dfe479b06321642caad3e903d03a7695e9b..05c3ce61a8bef3e89569fc56bc3c97b2d7888760 100644 >--- a/Tools/WebKitTestRunner/TestInvocation.cpp >+++ b/Tools/WebKitTestRunner/TestInvocation.cpp >@@ -916,6 +916,39 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB > return nullptr; > } > >+ if (WKStringIsEqualToUTF8CString(messageName, "AddMockMediaDevice")) { >+ ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); >+ >+ WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); >+ WKRetainPtr<WKStringRef> persistentIDKey(AdoptWK, WKStringCreateWithUTF8CString("PersistentID")); >+ WKRetainPtr<WKStringRef> labelKey(AdoptWK, WKStringCreateWithUTF8CString("Label")); >+ WKRetainPtr<WKStringRef> typeKey(AdoptWK, WKStringCreateWithUTF8CString("Type")); >+ >+ auto persistentID = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, persistentIDKey.get())); >+ auto label = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, labelKey.get())); >+ auto type = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, typeKey.get())); >+ >+ TestController::singleton().addMockMediaDevice(persistentID, label, type); >+ return nullptr; >+ } >+ >+ if (WKStringIsEqualToUTF8CString(messageName, "ClearMockMediaDevices")) { >+ TestController::singleton().clearMockMediaDevices(); >+ return nullptr; >+ } >+ >+ if (WKStringIsEqualToUTF8CString(messageName, "RemoveMockMediaDevice")) { >+ WKStringRef persistentId = static_cast<WKStringRef>(messageBody); >+ >+ TestController::singleton().removeMockMediaDevice(persistentId); >+ return nullptr; >+ } >+ >+ if (WKStringIsEqualToUTF8CString(messageName, "ResetMockMediaDevices")) { >+ TestController::singleton().resetMockMediaDevices(); >+ return nullptr; >+ } >+ > #if PLATFORM(MAC) > if (WKStringIsEqualToUTF8CString(messageName, "ConnectMockGamepad")) { > ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 9d67f5c3f7366efc2084b74d4f421086966c220a..b72e342eea59924de8336761ae188f7745cbc168 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2018-06-25 Youenn Fablet <youenn@apple.com> >+ >+ Add API to control mock media devices >+ https://bugs.webkit.org/show_bug.cgi?id=186958 >+ >+ Reviewed by Eric Carlson. >+ >+ * fast/mediastream/device-change-event-2-expected.txt: Added. >+ * fast/mediastream/device-change-event-2.html: Added. >+ > 2018-06-25 Antoine Quint <graouts@apple.com> > > [Web Animations] Make imported/mozilla/css-animations/test_animation-pausing.html pass reliably >diff --git a/LayoutTests/fast/mediastream/device-change-event-2-expected.txt b/LayoutTests/fast/mediastream/device-change-event-2-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..64c6b61076faaa3de4f8168f7969cf10f607a69d >--- /dev/null >+++ b/LayoutTests/fast/mediastream/device-change-event-2-expected.txt >@@ -0,0 +1,3 @@ >+ >+PASS 'devicechange' event fired when device list changes >+ >diff --git a/LayoutTests/fast/mediastream/device-change-event-2.html b/LayoutTests/fast/mediastream/device-change-event-2.html >new file mode 100644 >index 0000000000000000000000000000000000000000..43d5f2bdfedd91ecbd23fc71b83571e0707b255b >--- /dev/null >+++ b/LayoutTests/fast/mediastream/device-change-event-2.html >@@ -0,0 +1,58 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <meta charset="utf-8"> >+ <title>Testing local audio capture playback causes "playing" event to fire</title> >+ <script src="../../resources/testharness.js"></script> >+ <script src="../../resources/testharnessreport.js"></script> >+ <script> >+ let deviceIds = []; >+ promise_test(async (test) => { >+ if (!window.testRunner) >+ return Promise.reject("test requires internal API"); >+ >+ test.add_cleanup(() => { testRunner.resetMockMediaDevices(); }); >+ >+ testRunner.setUserMediaPermission(true); >+ >+ await navigator.mediaDevices.getUserMedia({ audio:true, video:true }); >+ >+ let devices = await navigator.mediaDevices.enumerateDevices(); >+ >+ assert_true(!!devices.length, "check there are some devices"); >+ >+ testRunner.clearMockMediaDevices(); >+ >+ devices = await navigator.mediaDevices.enumerateDevices(); >+ assert_false(!!devices.length, "check there are no more devices"); >+ >+ await new Promise((resolve, reject) => { >+ navigator.mediaDevices.ondevicechange = resolve; >+ setTimeout(() => { >+ console.log("event 1 taking a long time"); >+ resolve(); >+ }, 5000); >+ testRunner.addMockCameraDevice("id1", "my camera"); >+ }); >+ devices = await navigator.mediaDevices.enumerateDevices(); >+ assert_equals(devices[0].kind, "videoinput"); >+ assert_equals(devices[0].label, "my camera"); >+ >+ await new Promise((resolve, reject) => { >+ navigator.mediaDevices.ondevicechange = resolve; >+ setTimeout(() => { >+ console.log("event 2 taking a long time"); >+ resolve(); >+ }, 5000); >+ testRunner.addMockMicrophoneDevice("id2", "my mic"); >+ }); >+ devices = await navigator.mediaDevices.enumerateDevices(); >+ assert_equals(devices[0].kind, "audioinput"); >+ assert_equals(devices[0].label, "my mic"); >+ >+ }, "'devicechange' event fired when device list changes"); >+ </script> >+</head> >+<body> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186958
:
343414
|
343418
|
343441
|
343508
|
343517