WebKit Bugzilla
Attachment 347366 Details for
Bug 188521
: [MediaStream] Move capture device monitoring to WebKit
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-188521-20180817103604.patch (text/plain), 70.45 KB, created by
Eric Carlson
on 2018-08-17 10:36:05 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Eric Carlson
Created:
2018-08-17 10:36:05 PDT
Size:
70.45 KB
patch
obsolete
>Subversion Revision: 234888 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index c052c632521fffed7f6a1b9181d118bdd56bcd27..6851c86d2acdce34f7d116d18fe5c05429bd8304 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,67 @@ >+2018-08-15 Eric Carlson <eric.carlson@apple.com> >+ >+ [MediaStream] Move capture device monitoring to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188521 >+ <rdar://problem/43251787> >+ >+ Reviewed by Youenn Fablet. >+ >+ No new tests, updated fast/mediastream/device-change-event-2.html for the changes. >+ >+ * Modules/mediastream/MediaDevices.cpp: >+ (WebCore::MediaDevices::MediaDevices): Device change listener is added in addEventListener. >+ (WebCore::MediaDevices::stop): Device change listener is on the user media controller. >+ (WebCore::MediaDevices::addEventListener): Add the device change listener only once the first >+ event handler is added. >+ * Modules/mediastream/MediaDevices.h: >+ >+ * Modules/mediastream/UserMediaClient.h: >+ * Modules/mediastream/UserMediaController.h: >+ (WebCore::UserMediaController::addDeviceChangeObserver): Pass through to the client. >+ (WebCore::UserMediaController::removeDeviceChangeObserver): Ditto. >+ >+ * platform/mediastream/CaptureDeviceManager.cpp: >+ (CaptureDeviceManager::deviceChanged): Notify RealtimeMediaSourceCenter. >+ (nextObserverToken): Deleted. >+ (CaptureDeviceManager::addCaptureDeviceChangedObserver): Deleted. >+ (CaptureDeviceManager::removeCaptureDeviceChangedObserver): Deleted. >+ * platform/mediastream/CaptureDeviceManager.h: >+ >+ * platform/mediastream/RealtimeMediaSourceCenter.cpp: >+ (WebCore::RealtimeMediaSourceCenter::setDevicesChangedObserver): >+ (WebCore::RealtimeMediaSourceCenter::captureDevicesChanged): >+ (WebCore::observerMap): Deleted. >+ (WebCore::RealtimeMediaSourceCenter::addDevicesChangedObserver): Deleted. >+ (WebCore::RealtimeMediaSourceCenter::removeDevicesChangedObserver): Deleted. >+ * platform/mediastream/RealtimeMediaSourceCenter.h: >+ >+ * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm: >+ (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices): Call base class. >+ >+ * platform/mediastream/mac/AVCaptureDeviceManager.mm: >+ (WebCore::AVCaptureDeviceManager::deviceConnected): Ditto. >+ (WebCore::AVCaptureDeviceManager::deviceDisconnected): Ditto. >+ >+ * platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp: >+ (WebCore::deviceHasInputStreams): Drive-by fix, check the number of buffers to see if the >+ device has input streams. >+ (WebCore::CoreAudioCaptureDeviceManager::coreAudioCaptureDevices): Use new bool parameter >+ added to refreshAudioCaptureDevices so we won't trigger a device change event on the first scan. >+ (WebCore::CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices): Add param. >+ (WebCore::CoreAudioCaptureDeviceManager::devicesChanged): Use new param. >+ * platform/mediastream/mac/CoreAudioCaptureDeviceManager.h: >+ >+ * platform/mock/MockRealtimeMediaSourceCenter.cpp: >+ (WebCore::MockRealtimeMediaSourceCenter::setDevices): Don't need to call captureDevicesChanged, >+ it is done in the UI process. >+ (WebCore::MockRealtimeMediaSourceCenter::addDevice): Ditto. >+ (WebCore::MockRealtimeMediaSourceCenter::removeDevice): Ditto. >+ >+ * testing/InternalSettings.cpp: >+ (WebCore::InternalSettings::setPageIsFocusedAndActive): New, used by updated test. >+ * testing/Internals.h: >+ * testing/Internals.idl: >+ > 2018-08-15 Wenson Hsieh <wenson_hsieh@apple.com> > > [Attachment SPI] Remove attachment display mode options >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 65b78a253c9de6d06d570c6bdfef158d67ac774b..17058f3cc77d963061bbd23eb393067b4b377a6a 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,57 @@ >+2018-08-15 Eric Carlson <eric.carlson@apple.com> >+ >+ [MediaStream] Move capture device monitoring to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188521 >+ <rdar://problem/43251787> >+ >+ Reviewed by Youenn Fablet. >+ >+ * UIProcess/UserMediaPermissionRequestManagerProxy.cpp: >+ (WebKit::UserMediaPermissionRequestManagerProxy::captureDevicesChanged): Notify as appropriate. >+ (WebKit::UserMediaPermissionRequestManagerProxy::viewIsBecomingVisible): Change name from >+ viewIsBecomingVisible. Call captureDevicesChanged if a change happened when not visible. >+ (WebKit::UserMediaPermissionRequestManagerProxy::watchdogTimerFired): Clear m_pendingDeviceChangeEvent. >+ (WebKit::UserMediaPermissionRequestManagerProxy::processPregrantedRequests): Deleted. >+ * UIProcess/UserMediaPermissionRequestManagerProxy.h: >+ >+ * UIProcess/UserMediaProcessManager.cpp: >+ (WebKit::UserMediaProcessManager::UserMediaProcessManager): Initialize timer. >+ (WebKit::UserMediaProcessManager::captureDevicesChanged): New, notify each manager. >+ (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices): Cache the device list and >+ register device change listener the first time it is called. >+ * UIProcess/UserMediaProcessManager.h: >+ >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::viewIsBecomingVisible): >+ (WebKit::WebPageProxy::beginMonitoringCaptureDevices): >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ >+ * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp: >+ (WebKit::UserMediaPermissionRequestManager::addDeviceChangeObserver): Add listener, tell page >+ to start monitoring device changes. >+ (WebKit::UserMediaPermissionRequestManager::removeDeviceChangeObserver): Remove listener. >+ (WebKit::UserMediaPermissionRequestManager::captureDevicesChanged): Call listeners. >+ * WebProcess/MediaStream/UserMediaPermissionRequestManager.h: >+ >+ * WebProcess/WebCoreSupport/WebUserMediaClient.cpp: >+ (WebKit::WebUserMediaClient::addDeviceChangeObserver): >+ (WebKit::WebUserMediaClient::removeDeviceChangeObserver): >+ * WebProcess/WebCoreSupport/WebUserMediaClient.h: >+ >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::captureDevicesChanged): >+ * WebProcess/WebPage/WebPage.h: >+ * WebProcess/WebPage/WebPage.messages.in: >+ >+ * WebProcess/WebProcess.cpp: >+ (WebKit::WebProcess::addMockMediaDevice): >+ (WebKit::WebProcess::clearMockMediaDevices): >+ (WebKit::WebProcess::removeMockMediaDevice): >+ (WebKit::WebProcess::resetMockMediaDevices): >+ (WebKit::WebProcess::captureDevicesChanged): >+ * WebProcess/WebProcess.h: >+ > 2018-08-15 Michael Catanzaro <mcatanzaro@igalia.com> > > [WPE][GTK] WaylandCompositor fails to properly remove surface from its page map >diff --git a/Source/WebCore/Modules/mediastream/MediaDevices.cpp b/Source/WebCore/Modules/mediastream/MediaDevices.cpp >index be9051c93994d5bbc10a0d8aa69419b1714aeeab..6e5a9aa7fec504dcdfe61b44357a451c7edf5615 100644 >--- a/Source/WebCore/Modules/mediastream/MediaDevices.cpp >+++ b/Source/WebCore/Modules/mediastream/MediaDevices.cpp >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2015 Ericsson AB. All rights reserved. >- * Copyright (C) 2015-2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2015-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 >@@ -41,6 +41,7 @@ > #include "MediaTrackSupportedConstraints.h" > #include "RealtimeMediaSourceSettings.h" > #include "RuntimeEnabledFeatures.h" >+#include "UserMediaController.h" > #include "UserMediaRequest.h" > #include <wtf/RandomNumber.h> > >@@ -51,17 +52,6 @@ inline MediaDevices::MediaDevices(Document& document) > , m_scheduledEventTimer(*this, &MediaDevices::scheduledEventTimerFired) > , m_eventNames(eventNames()) > { >- m_deviceChangedToken = RealtimeMediaSourceCenter::singleton().addDevicesChangedObserver([weakThis = makeWeakPtr(*this), this]() { >- >- if (!weakThis) >- return; >- >- // FIXME: We should only dispatch an event if the user has been granted access to the type of >- // device that was added or removed. >- if (!m_scheduledEventTimer.isActive()) >- 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"); >@@ -74,8 +64,12 @@ MediaDevices::~MediaDevices() = default; > > void MediaDevices::stop() > { >- if (m_deviceChangedToken) >- RealtimeMediaSourceCenter::singleton().removeDevicesChangedObserver(m_deviceChangedToken); >+ if (m_deviceChangeToken) { >+ auto* document = this->document(); >+ auto* controller = document ? UserMediaController::from(document->page()) : nullptr; >+ if (document && controller) >+ controller->removeDeviceChangeObserver(m_deviceChangeToken); >+ } > } > > Ref<MediaDevices> MediaDevices::create(Document& document) >@@ -181,6 +175,27 @@ bool MediaDevices::canSuspendForDocumentSuspension() const > return true; > } > >+bool MediaDevices::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options) >+{ >+ if (!m_listeningForDeviceChanges && eventType == eventNames().devicechangeEvent) { >+ auto* document = this->document(); >+ auto* controller = document ? UserMediaController::from(document->page()) : nullptr; >+ if (document && controller) { >+ m_listeningForDeviceChanges = true; >+ >+ m_deviceChangeToken = controller->addDeviceChangeObserver([weakThis = makeWeakPtr(*this), this]() { >+ >+ if (!weakThis || m_scheduledEventTimer.isActive()) >+ return; >+ >+ m_scheduledEventTimer.startOneShot(Seconds(randomNumber() / 2)); >+ }); >+ } >+ } >+ >+ return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), options); >+} >+ > } // namespace WebCore > > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/Modules/mediastream/MediaDevices.h b/Source/WebCore/Modules/mediastream/MediaDevices.h >index 02d1aef9d6f317867a97f195be90614859549cf5..072ba15d496e3a6b872f109a963582d2f200d94c 100644 >--- a/Source/WebCore/Modules/mediastream/MediaDevices.h >+++ b/Source/WebCore/Modules/mediastream/MediaDevices.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2015 Ericsson AB. All rights reserved. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-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 >@@ -41,11 +41,11 @@ > #include "MediaTrackConstraints.h" > #include "RealtimeMediaSourceCenter.h" > #include "Timer.h" >+#include "UserMediaClient.h" > #include <wtf/WeakPtr.h> > > namespace WebCore { > >-class Document; > class MediaDeviceInfo; > class MediaStream; > >@@ -85,6 +85,7 @@ private: > explicit MediaDevices(Document&); > > void scheduledEventTimerFired(); >+ bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override; > > friend class JSMediaDevicesOwner; > >@@ -101,8 +102,9 @@ private: > void derefEventTarget() final { deref(); } > > Timer m_scheduledEventTimer; >- RealtimeMediaSourceCenter::DevicesChangedObserverToken m_deviceChangedToken; >+ UserMediaClient::DeviceChangeObserverToken m_deviceChangeToken; > const EventNames& m_eventNames; // Need to cache this so we can use it from GC threads. >+ bool m_listeningForDeviceChanges { false }; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/mediastream/UserMediaClient.h b/Source/WebCore/Modules/mediastream/UserMediaClient.h >index 3e3ade1a8c2bd5ea70c027632d760e3a01737dbf..b2aa5603f575127e5f5a8646a9a877e214a4a618 100644 >--- a/Source/WebCore/Modules/mediastream/UserMediaClient.h >+++ b/Source/WebCore/Modules/mediastream/UserMediaClient.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2011 Ericsson AB. All rights reserved. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-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 >@@ -33,6 +33,8 @@ > > #if ENABLE(MEDIA_STREAM) > >+#include <wtf/ObjectIdentifier.h> >+ > namespace WebCore { > > class MediaDevicesEnumerationRequest; >@@ -49,6 +51,11 @@ public: > virtual void enumerateMediaDevices(MediaDevicesEnumerationRequest&) = 0; > virtual void cancelMediaDevicesEnumerationRequest(MediaDevicesEnumerationRequest&) = 0; > >+ enum DeviceChangeObserverTokenType { }; >+ using DeviceChangeObserverToken = ObjectIdentifier<DeviceChangeObserverTokenType>; >+ virtual DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&) = 0; >+ virtual void removeDeviceChangeObserver(DeviceChangeObserverToken) = 0; >+ > protected: > virtual ~UserMediaClient() = default; > }; >diff --git a/Source/WebCore/Modules/mediastream/UserMediaController.h b/Source/WebCore/Modules/mediastream/UserMediaController.h >index 2249abf2786bd2235c40188c4ac44aa187d62bf5..cfac599d7fbe34bd50404849165e53fbb3a5b1b1 100644 >--- a/Source/WebCore/Modules/mediastream/UserMediaController.h >+++ b/Source/WebCore/Modules/mediastream/UserMediaController.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2012 Google Inc. All rights reserved. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-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 >@@ -48,6 +48,9 @@ public: > void enumerateMediaDevices(MediaDevicesEnumerationRequest&); > void cancelMediaDevicesEnumerationRequest(MediaDevicesEnumerationRequest&); > >+ UserMediaClient::DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&); >+ void removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken); >+ > WEBCORE_EXPORT static const char* supplementName(); > static UserMediaController* from(Page* page) { return static_cast<UserMediaController*>(Supplement<Page>::from(page, supplementName())); } > >@@ -75,6 +78,16 @@ inline void UserMediaController::cancelMediaDevicesEnumerationRequest(MediaDevic > m_client->cancelMediaDevicesEnumerationRequest(request); > } > >+inline UserMediaClient::DeviceChangeObserverToken UserMediaController::addDeviceChangeObserver(WTF::Function<void()>&& observer) >+{ >+ return m_client->addDeviceChangeObserver(WTFMove(observer)); >+} >+ >+inline void UserMediaController::removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken token) >+{ >+ m_client->removeDeviceChangeObserver(token); >+} >+ > } // namespace WebCore > > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h >index 654205aed7988630ab83bd50ff8784ef75bf4dcb..0c528784b522a253761e249b26a85eb7e1f96d75 100644 >--- a/Source/WebCore/page/Page.h >+++ b/Source/WebCore/page/Page.h >@@ -434,8 +434,8 @@ public: > void setIsRestoringCachedPage(bool value) { m_isRestoringCachedPage = value; } > bool isRestoringCachedPage() const { return m_isRestoringCachedPage; } > >- void addActivityStateChangeObserver(ActivityStateChangeObserver&); >- void removeActivityStateChangeObserver(ActivityStateChangeObserver&); >+ WEBCORE_EXPORT void addActivityStateChangeObserver(ActivityStateChangeObserver&); >+ WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&); > > WEBCORE_EXPORT void suspendScriptedAnimations(); > WEBCORE_EXPORT void resumeScriptedAnimations(); >diff --git a/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp b/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp >index cd147a02b4cd7c0e8127f97ac039865a4f6728ed..8a39b292f938acd4905902a45ac4af8a87550cc0 100644 >--- a/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp >+++ b/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2015-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2015-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 >@@ -50,24 +50,14 @@ CaptureDevice CaptureDeviceManager::captureDeviceFromPersistentID(const String& > return { }; > } > >-static CaptureDeviceManager::ObserverToken nextObserverToken() >+void CaptureDeviceManager::deviceChanged() > { >- static CaptureDeviceManager::ObserverToken nextToken = 0; >- return ++nextToken; >-} >- >-CaptureDeviceManager::ObserverToken CaptureDeviceManager::addCaptureDeviceChangedObserver(CaptureDeviceChangedCallback&& observer) >-{ >- auto token = nextObserverToken(); >- m_observers.set(token, WTFMove(observer)); >- return token; >-} >+ callOnMainThread([weakThis = makeWeakPtr(*this)] { >+ if (!weakThis) >+ return; > >-void CaptureDeviceManager::removeCaptureDeviceChangedObserver(ObserverToken token) >-{ >- ASSERT(m_observers.contains(token)); >- m_observers.remove(token); >+ RealtimeMediaSourceCenter::singleton().captureDevicesChanged(); >+ }); > } > >- > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mediastream/CaptureDeviceManager.h b/Source/WebCore/platform/mediastream/CaptureDeviceManager.h >index 45edb300c3b72e877345c9f00236fd06d3549cde..5732de03deeb4fc0985a1b1a74bcbb1460fec5bd 100644 >--- a/Source/WebCore/platform/mediastream/CaptureDeviceManager.h >+++ b/Source/WebCore/platform/mediastream/CaptureDeviceManager.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2015-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2015-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 >@@ -29,23 +29,19 @@ > > #include "CaptureDevice.h" > #include "RealtimeMediaSource.h" >+#include <wtf/WeakPtr.h> > > namespace WebCore { > >-class CaptureDeviceManager { >+class CaptureDeviceManager : public CanMakeWeakPtr<CaptureDeviceManager> { > public: >- using CaptureDeviceChangedCallback = WTF::Function<void()>; >- using ObserverToken = uint32_t; >- virtual ObserverToken addCaptureDeviceChangedObserver(CaptureDeviceChangedCallback&&); >- virtual void removeCaptureDeviceChangedObserver(ObserverToken); >- > virtual const Vector<CaptureDevice>& captureDevices() = 0; > virtual std::optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return std::nullopt; } > > protected: > virtual ~CaptureDeviceManager(); > CaptureDevice captureDeviceFromPersistentID(const String& captureDeviceID); >- HashMap<ObserverToken, CaptureDeviceChangedCallback> m_observers; >+ void deviceChanged(); > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >index bfe4d6de1c8340682a1f7ee29e8c94585fe0bce8..8a4609a2d2647410689bf402a2c1d634612c7fd1 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >@@ -286,7 +286,7 @@ bool RealtimeMediaSource::supportsSizeAndFrameRate(std::optional<IntConstraint> > badConstraint = frameRateConstraint->name(); > return false; > } >- >+ > return true; > } > >@@ -754,7 +754,7 @@ bool RealtimeMediaSource::supportsConstraint(const MediaConstraint& constraint) > // Unknown (or unsupported) constraints should be ignored. > break; > } >- >+ > return false; > } > >@@ -765,7 +765,7 @@ bool RealtimeMediaSource::supportsConstraints(const MediaConstraints& constraint > FlattenedConstraint candidates; > if (!selectSettings(constraints, candidates, invalidConstraint, SelectType::ForSupportsConstraints)) > return false; >- >+ > return true; > } > >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp >index 3886ff875ce89f5c108c437bb9caa2f4d7f1602a..ffd51d4e46d5e8aaa2a23a062aa124f852f3fc46 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp >@@ -1,7 +1,7 @@ > /* > * Copyright (C) 2011 Ericsson AB. All rights reserved. > * Copyright (C) 2012 Google Inc. All rights reserved. >- * Copyright (C) 2013-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-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 >@@ -53,12 +53,6 @@ static RealtimeMediaSourceCenter*& mediaStreamCenterOverride() > return override; > } > >-static HashMap<unsigned, std::function<void()>>& observerMap() >-{ >- static NeverDestroyed<HashMap<unsigned, std::function<void()>>> map; >- return map; >-} >- > RealtimeMediaSourceCenter& RealtimeMediaSourceCenter::singleton() > { > RealtimeMediaSourceCenter* override = mediaStreamCenterOverride(); >@@ -199,25 +193,18 @@ ExceptionOr<void> RealtimeMediaSourceCenter::setDeviceEnabled(const String& id, > return Exception { NotFoundError }; > } > >-RealtimeMediaSourceCenter::DevicesChangedObserverToken RealtimeMediaSourceCenter::addDevicesChangedObserver(std::function<void()>&& observer) >-{ >- static DevicesChangedObserverToken nextToken = 0; >- observerMap().set(++nextToken, WTFMove(observer)); >- return nextToken; >-} >- >-void RealtimeMediaSourceCenter::removeDevicesChangedObserver(DevicesChangedObserverToken token) >+void RealtimeMediaSourceCenter::setDevicesChangedObserver(std::function<void()>&& observer) > { >- bool wasRemoved = observerMap().remove(token); >- ASSERT_UNUSED(wasRemoved, wasRemoved); >+ ASSERT(isMainThread()); >+ ASSERT(!m_deviceChangedObserver); >+ m_deviceChangedObserver = WTFMove(observer); > } > > void RealtimeMediaSourceCenter::captureDevicesChanged() > { >- // Copy the hash map because the observer callback may call back in and modify the map. >- auto callbacks = observerMap(); >- for (auto& it : callbacks) >- it.value(); >+ ASSERT(isMainThread()); >+ if (m_deviceChangedObserver) >+ m_deviceChangedObserver(); > } > > void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt) >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >index ef7b3cfcd916edccae620e4421f8c0babe8fe3ec..d54ae8e7fa57d32571e0730cd629775488dfcf61 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h >@@ -1,7 +1,7 @@ > /* > * Copyright (C) 2011 Ericsson AB. All rights reserved. > * Copyright (C) 2012 Google Inc. All rights reserved. >- * Copyright (C) 2013-2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-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 >@@ -85,22 +85,22 @@ public: > WEBCORE_EXPORT CaptureDevice captureDeviceWithUniqueID(const String& id, const String& hashSalt); > WEBCORE_EXPORT ExceptionOr<void> setDeviceEnabled(const String&, bool); > >- using DevicesChangedObserverToken = unsigned; >- DevicesChangedObserverToken addDevicesChangedObserver(std::function<void()>&&); >- void removeDevicesChangedObserver(DevicesChangedObserverToken); >+ WEBCORE_EXPORT void setDevicesChangedObserver(std::function<void()>&&); > > void setVideoCapturePageState(bool, bool); > >+ void captureDevicesChanged(); >+ > protected: > RealtimeMediaSourceCenter(); > >- void captureDevicesChanged(); >- > static RealtimeMediaSourceCenter& platformCenter(); > RealtimeMediaSourceSupportedConstraints m_supportedConstraints; > > CaptureDeviceManager* m_audioCaptureDeviceManager { nullptr }; > CaptureDeviceManager* m_videoCaptureDeviceManager { nullptr }; >+ >+ WTF::Function<void()> m_deviceChangedObserver; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm >index 32e70e16dca306f5fd790d2e34515781f7776f4e..f61d8dfaf623b6400ed8547cc778d6f58d33c933 100644 >--- a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm >+++ b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2017-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 >@@ -29,6 +29,7 @@ > #if ENABLE(MEDIA_STREAM) && PLATFORM(IOS) > > #include "AVAudioSessionCaptureDevice.h" >+#include "RealtimeMediaSourceCenter.h" > #include <AVFoundation/AVAudioSession.h> > #include <wtf/SoftLinking.h> > #include <wtf/Vector.h> >@@ -141,8 +142,7 @@ void AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices() > m_audioSessionCaptureDevices = WTFMove(newAudioDevices); > m_devices = WTFMove(newDevices); > >- for (auto& observer : m_observers.values()) >- observer(); >+ deviceChanged(); > } > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm b/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm >index c011b26e686b05c1fa0b69a0d91d7cf0ca63f340..0efc92a0fee902ad9689e6ceacc55a6572f4fbd9 100644 >--- a/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm >+++ b/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013-2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-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 >@@ -179,9 +179,7 @@ void AVCaptureDeviceManager::registerForDeviceNotifications() > void AVCaptureDeviceManager::deviceConnected() > { > refreshCaptureDevices(); >- >- for (auto& observer : m_observers.values()) >- observer(); >+ deviceChanged(); > } > > void AVCaptureDeviceManager::deviceDisconnected(AVCaptureDeviceTypedef* device) >@@ -200,8 +198,7 @@ void AVCaptureDeviceManager::deviceDisconnected(AVCaptureDeviceTypedef* device) > } > } > >- for (auto& observer : m_observers.values()) >- observer(); >+ deviceChanged(); > } > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp >index 5413a8f86722204e4c42fae6eedb306a52f551a8..1111eab0320f41be16b308fb70843443bef4e941 100644 >--- a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp >+++ b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2017-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 >@@ -30,6 +30,7 @@ > > #include "CoreAudioCaptureDevice.h" > #include "Logging.h" >+#include "RealtimeMediaSourceCenter.h" > #include <AudioUnit/AudioUnit.h> > #include <CoreMedia/CMSync.h> > #include <wtf/Assertions.h> >@@ -64,10 +65,17 @@ std::optional<CaptureDevice> CoreAudioCaptureDeviceManager::captureDeviceWithPer > static bool deviceHasInputStreams(AudioObjectID deviceID) > { > UInt32 dataSize = 0; >- AudioObjectPropertyAddress address = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeInput, kAudioObjectPropertyElementMaster }; >+ AudioObjectPropertyAddress address = { kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyScopeInput, kAudioObjectPropertyElementMaster }; > auto err = AudioObjectGetPropertyDataSize(deviceID, &address, 0, nullptr, &dataSize); > >- return !err && dataSize; >+ if (err || !dataSize) >+ return false; >+ >+ auto bufferList = std::unique_ptr<AudioBufferList>((AudioBufferList*) ::operator new (dataSize)); >+ memset(bufferList.get(), 0, dataSize); >+ err = AudioObjectGetPropertyData(deviceID, &address, 0, nullptr, &dataSize, bufferList.get()); >+ >+ return !err && bufferList->mNumberBuffers; > } > > static bool isValidCaptureDevice(const CoreAudioCaptureDevice& device) >@@ -81,7 +89,7 @@ Vector<CoreAudioCaptureDevice>& CoreAudioCaptureDeviceManager::coreAudioCaptureD > static bool initialized; > if (!initialized) { > initialized = true; >- refreshAudioCaptureDevices(); >+ refreshAudioCaptureDevices(DoNotNotify); > > AudioObjectPropertyAddress address = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; > auto err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &address, devicesChanged, this); >@@ -102,7 +110,7 @@ std::optional<CoreAudioCaptureDevice> CoreAudioCaptureDeviceManager::coreAudioDe > } > > >-void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices() >+void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices(NotifyIfDevicesHaveChanged notify) > { > AudioObjectPropertyAddress address = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; > UInt32 dataSize = 0; >@@ -156,13 +164,13 @@ void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices() > m_devices.append(captureDevice); > } > >- for (auto& observer : m_observers.values()) >- observer(); >+ if (notify == Notify) >+ deviceChanged(); > } > > OSStatus CoreAudioCaptureDeviceManager::devicesChanged(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void* userData) > { >- static_cast<CoreAudioCaptureDeviceManager*>(userData)->refreshAudioCaptureDevices(); >+ static_cast<CoreAudioCaptureDeviceManager*>(userData)->refreshAudioCaptureDevices(Notify); > return 0; > } > >diff --git a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h >index 8c28e827984caff486a45541905510375a45902d..cf48276414b242aafa486d9250375c8814cc1b9f 100644 >--- a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h >+++ b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2017-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 >@@ -55,7 +55,8 @@ private: > static OSStatus devicesChanged(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void*); > Vector<CoreAudioCaptureDevice>& coreAudioCaptureDevices(); > >- void refreshAudioCaptureDevices(); >+ enum NotifyIfDevicesHaveChanged { Notify, DoNotNotify }; >+ void refreshAudioCaptureDevices(NotifyIfDevicesHaveChanged); > > Vector<CaptureDevice> m_devices; > Vector<CoreAudioCaptureDevice> m_coreAudioCaptureDevices; >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp b/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >index 0875497a1efa110453f8e2d6e523dab3617c94af..ec441efd75e9387676655bd025d937b5387737a3 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp >@@ -97,6 +97,7 @@ void MockRealtimeMediaSource::createCaptureDevice(const MockMediaDevice& device) > void MockRealtimeMediaSource::resetDevices() > { > setDevices(defaultDevices()); >+ RealtimeMediaSourceCenter::singleton().captureDevicesChanged(); > } > > void MockRealtimeMediaSource::setDevices(Vector<MockMediaDevice>&& newMockDevices) >@@ -115,6 +116,7 @@ void MockRealtimeMediaSource::setDevices(Vector<MockMediaDevice>&& newMockDevice > map.add(device.persistentId, device); > createCaptureDevice(device); > } >+ RealtimeMediaSourceCenter::singleton().captureDevicesChanged(); > } > > void MockRealtimeMediaSource::addDevice(const MockMediaDevice& device) >@@ -122,6 +124,7 @@ void MockRealtimeMediaSource::addDevice(const MockMediaDevice& device) > devices().append(device); > deviceMap().set(device.persistentId, device); > createCaptureDevice(device); >+ RealtimeMediaSourceCenter::singleton().captureDevicesChanged(); > } > > void MockRealtimeMediaSource::removeDevice(const String& persistentId) >@@ -140,6 +143,7 @@ void MockRealtimeMediaSource::removeDevice(const String& persistentId) > }); > > map.remove(iterator); >+ RealtimeMediaSourceCenter::singleton().captureDevicesChanged(); > } > > std::optional<CaptureDevice> MockRealtimeMediaSource::captureDeviceWithPersistentID(CaptureDevice::DeviceType type, const String& id) >diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >index df91ebe0fe8544114a662c76e42afca7a700edac..db68821e31d2ce27d8be18dfd57e06fe3056a395 100644 >--- a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >+++ b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2013 Google Inc. All rights reserved. >- * Copyright (C) 2013 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. > * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). > * > * Redistribution and use in source and binary forms, with or without >@@ -55,19 +55,16 @@ void MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(bool > 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 >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index 13b7b707e2738e33f810ce49ccd5a1af0bd72745..263fd4cc1aa038c8f78bc11ad34b0b0802fa278f 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -4338,6 +4338,22 @@ void Internals::setPageVisibility(bool isVisible) > page.setActivityState(state); > } > >+void Internals::setPageIsFocusedAndActive(bool isFocusedAndActive) >+{ >+ auto* document = contextDocument(); >+ if (!document || !document->page()) >+ return; >+ auto& page = *document->page(); >+ auto state = page.activityState(); >+ >+ if (isFocusedAndActive) >+ state |= (ActivityState::WindowIsActive | ActivityState::IsFocused); >+ else >+ state &= ~(ActivityState::WindowIsActive | ActivityState::IsFocused); >+ >+ page.setActivityState(state); >+} >+ > #if ENABLE(WEB_RTC) > void Internals::setH264HardwareEncoderAllowed(bool allowed) > { >diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h >index d0d2879ce6f6737945d57379147b6376d344646f..e1182de54d86e54f9911296b76d3d153710fd3f4 100644 >--- a/Source/WebCore/testing/Internals.h >+++ b/Source/WebCore/testing/Internals.h >@@ -641,6 +641,8 @@ public: > #endif > > void setPageVisibility(bool isVisible); >+ void setPageIsFocusedAndActive(bool); >+ > > #if ENABLE(WEB_RTC) > void setH264HardwareEncoderAllowed(bool allowed); >diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl >index 01148b98d9b0f8bfb454a7d7411a6f6f64c8820f..919bbdaf2d0aa71adca79979cdc8fec20c2eaff9 100644 >--- a/Source/WebCore/testing/Internals.idl >+++ b/Source/WebCore/testing/Internals.idl >@@ -603,6 +603,7 @@ enum CompositingPolicy { > [Conditional=WEBGL] void failNextGPUStatusCheck(WebGLRenderingContext context); > > void setPageVisibility(boolean isVisible); >+ void setPageIsFocusedAndActive(boolean isFocused); > > [Conditional=WEB_RTC] void setH264HardwareEncoderAllowed(boolean allowed); > [Conditional=WEB_RTC] void applyRotationForOutgoingVideoSources(RTCPeerConnection connection); >diff --git a/Source/WebKit/Scripts/webkit/messages.py b/Source/WebKit/Scripts/webkit/messages.py >index a782baac9d45bb3c9d0b8992622faa6252aa184d..09e464fcd7160b2ee8fe2c93362026eb4b380d89 100644 >--- a/Source/WebKit/Scripts/webkit/messages.py >+++ b/Source/WebKit/Scripts/webkit/messages.py >@@ -419,6 +419,7 @@ def headers_for_type(type): > 'WebCore::SelectionRect': ['"EditorState.h"'], > 'WebKit::ActivityStateChangeID': ['"DrawingAreaInfo.h"'], > 'WebKit::BackForwardListItemState': ['"SessionState.h"'], >+ 'WebKit::DeviceAccessState': ['"UserMediaPermissionRequestManager.h"'], > 'WebKit::LayerHostingMode': ['"LayerTreeContext.h"'], > 'WebKit::PageState': ['"SessionState.h"'], > 'WebKit::WebGestureEvent': ['"WebEvent.h"'], >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >index 3c07295f1053fc15dcc88445632905b8c3fcb96b..02b2a231e6796382aa1a400a49e78014b86efc4a 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >+++ b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016-2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -22,6 +22,7 @@ > > #include "APISecurityOrigin.h" > #include "APIUIClient.h" >+#include "UserMediaPermissionRequestManager.h" > #include "UserMediaProcessManager.h" > #include "WebAutomationSession.h" > #include "WebPageMessages.h" >@@ -77,6 +78,15 @@ void UserMediaPermissionRequestManagerProxy::stopCapture() > m_page.stopMediaCapture(); > } > >+void UserMediaPermissionRequestManagerProxy::captureDevicesChanged() >+{ >+#if ENABLE(MEDIA_STREAM) >+ // FIXME: a page with persistent access should always get device change notifications. >+ auto accessState = m_grantedRequests.isEmpty() ? DeviceAccessState::NoAccess : DeviceAccessState::SessionAccess; >+ m_page.process().send(Messages::WebPage::CaptureDevicesChanged(accessState), m_page.pageID()); >+#endif >+} >+ > void UserMediaPermissionRequestManagerProxy::clearCachedState() > { > invalidatePendingRequests(); >@@ -434,7 +444,7 @@ void UserMediaPermissionRequestManagerProxy::captureStateChanged(MediaProducer:: > #endif > } > >-void UserMediaPermissionRequestManagerProxy::processPregrantedRequests() >+void UserMediaPermissionRequestManagerProxy::viewIsBecomingVisible() > { > for (auto& request : m_pregrantedRequests) > request->allow(); >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >index 573af04d71b853957512499d92c430648bbd179f..8d3c09673c70c086c0b2b88edebf5b05bdaf6d1d 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >+++ b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -50,7 +50,7 @@ public: > void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, const WebCore::MediaStreamRequest&); > > void resetAccess(uint64_t mainFrameID); >- void processPregrantedRequests(); >+ void viewIsBecomingVisible(); > > void userMediaAccessWasGranted(uint64_t, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice); > void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason); >@@ -61,6 +61,7 @@ public: > void scheduleNextRejection(); > void rejectionTimerFired(); > void clearCachedState(); >+ void captureDevicesChanged(); > > void captureStateChanged(WebCore::MediaProducer::MediaStateFlags oldState, WebCore::MediaProducer::MediaStateFlags newState); > >diff --git a/Source/WebKit/UIProcess/UserMediaProcessManager.cpp b/Source/WebKit/UIProcess/UserMediaProcessManager.cpp >index 7ae6909746bfd7893d1ce9f309884dd3163bc4c2..7025d4d9991c59bb910025a3f480aa52bb0c39d6 100644 >--- a/Source/WebKit/UIProcess/UserMediaProcessManager.cpp >+++ b/Source/WebKit/UIProcess/UserMediaProcessManager.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -25,6 +25,7 @@ > #include "WebPageMessages.h" > #include "WebPageProxy.h" > #include "WebProcessProxy.h" >+#include <WebCore/RealtimeMediaSourceCenter.h> > #include <wtf/HashMap.h> > #include <wtf/NeverDestroyed.h> > >@@ -35,6 +36,8 @@ static const ASCIILiteral audioExtensionPath { "com.apple.webkit.microphone"_s } > static const ASCIILiteral videoExtensionPath { "com.apple.webkit.camera"_s }; > #endif > >+static const Seconds deviceChangeDebounceTimerInterval { 200_ms }; >+ > class ProcessState { > public: > ProcessState() { } >@@ -101,6 +104,11 @@ UserMediaProcessManager& UserMediaProcessManager::singleton() > return manager; > } > >+UserMediaProcessManager::UserMediaProcessManager() >+ : m_debounceTimer(RunLoop::main(), this, &UserMediaProcessManager::captureDevicesChanged) >+{ >+} >+ > void UserMediaProcessManager::addUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy& proxy) > { > processState(proxy.page().process()).addRequestManager(proxy); >@@ -254,6 +262,58 @@ void UserMediaProcessManager::setCaptureEnabled(bool enabled) > } > } > >+void UserMediaProcessManager::captureDevicesChanged() >+{ >+ auto& map = stateMap(); >+ for (auto& state : map) { >+ auto* process = state.key; >+ for (auto& manager : state.value->managers()) { >+ if (map.find(process) == map.end()) >+ break; >+ manager->captureDevicesChanged(); >+ } >+ } >+} >+ >+void UserMediaProcessManager::beginMonitoringCaptureDevices() >+{ >+ static std::once_flag onceFlag; >+ >+ std::call_once(onceFlag, [this] { >+ m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices(); >+ >+ WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() { >+ auto oldDevices = WTFMove(m_captureDevices); >+ m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices(); >+ >+ if (m_captureDevices.size() == oldDevices.size()) { >+ bool haveChanges = false; >+ for (auto &newDevice : m_captureDevices) { >+ if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone) >+ continue; >+ >+ auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) { >+ return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled(); >+ }); >+ >+ if (index == notFound) { >+ haveChanges = true; >+ break; >+ } >+ } >+ >+ if (!haveChanges) >+ return; >+ } >+ >+ // When a device with camera and microphone is attached or detached, the CaptureDevice notification for >+ // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks. >+ if (!m_debounceTimer.isActive()) >+ m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval); >+ }); >+ }); >+} >+ > } // namespace WebKit > > #endif >diff --git a/Source/WebKit/UIProcess/UserMediaProcessManager.h b/Source/WebKit/UIProcess/UserMediaProcessManager.h >index 81998b4acb7ddf91d50a83c79d2e5cac3d187473..ae16ebed85d80bfdcac05ec6b80c7643b8ef528b 100644 >--- a/Source/WebKit/UIProcess/UserMediaProcessManager.h >+++ b/Source/WebKit/UIProcess/UserMediaProcessManager.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -21,6 +21,8 @@ > #if ENABLE(MEDIA_STREAM) > > #include "UserMediaPermissionRequestManagerProxy.h" >+#include <WebCore/CaptureDevice.h> >+#include <wtf/RunLoop.h> > > namespace WebKit { > >@@ -31,6 +33,8 @@ public: > > static UserMediaProcessManager& singleton(); > >+ UserMediaProcessManager(); >+ > void addUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy&); > void removeUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy&); > >@@ -45,7 +49,13 @@ public: > > void denyNextUserMediaRequest() { m_denyNextRequest = true; } > >+ void beginMonitoringCaptureDevices(); >+ > private: >+ void captureDevicesChanged(); >+ >+ Vector<WebCore::CaptureDevice> m_captureDevices; >+ RunLoop::Timer<UserMediaProcessManager> m_debounceTimer; > bool m_captureEnabled { true }; > bool m_denyNextRequest { false }; > }; >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 2dc0f33885b690584f47117e69deeef28c022a47..95fbc120dd80b41307ee7284db82d29c2c6a81fe 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -3890,7 +3890,7 @@ void WebPageProxy::didChangeMainDocument(uint64_t frameID) > void WebPageProxy::viewIsBecomingVisible() > { > #if ENABLE(MEDIA_STREAM) >- userMediaPermissionRequestManager().processPregrantedRequests(); >+ userMediaPermissionRequestManager().viewIsBecomingVisible(); > #endif > } > >@@ -6524,6 +6524,13 @@ void WebPageProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t > #endif > } > >+void WebPageProxy::beginMonitoringCaptureDevices() >+{ >+#if ENABLE(MEDIA_STREAM) >+ UserMediaProcessManager::singleton().beginMonitoringCaptureDevices(); >+#endif >+} >+ > void WebPageProxy::clearUserMediaState() > { > #if ENABLE(MEDIA_STREAM) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index 6a5b259fcaea6d8928f09889c798045eb10d8815..185ecf017938ca545b17b03bfca7b9db8faa0405 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1491,6 +1491,7 @@ private: > #endif > void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginIdentifier, const WebCore::SecurityOriginData& topLevelDocumentOriginIdentifier, const WebCore::MediaStreamRequest&); > void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData); >+ void beginMonitoringCaptureDevices(); > > void runModal(); > void notifyScrollerThumbIsVisibleInRect(const WebCore::IntRect&); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in >index b31f5f0be34cc948927a9b136d0cc32c51bc9c2a..6d29a9fd2e463df9a0f06e0347fac6451b5c0864 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in >@@ -287,6 +287,7 @@ messages -> WebPageProxy { > # MediaSteam messages > RequestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, struct WebCore::SecurityOriginData userMediaDocumentOriginIdentifier, struct WebCore::SecurityOriginData topLevelDocumentOriginIdentifier, struct WebCore::MediaStreamRequest request) > EnumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, struct WebCore::SecurityOriginData userMediaDocumentOriginIdentifier, struct WebCore::SecurityOriginData topLevelDocumentOriginIdentifier) >+ BeginMonitoringCaptureDevices() > #endif > > # Notification messages >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index c833c1fee5b333a6a57a1f213946975309605754..366219002b11e11b0de337ed8a85fe7ef890933f 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -74,6 +74,7 @@ > 074E75FE1DF2211900D318EC /* UserMediaProcessManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 074E75FB1DF1FD1300D318EC /* UserMediaProcessManager.h */; }; > 074E76021DF707BE00D318EC /* MediaDeviceSandboxExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 074E76001DF7075D00D318EC /* MediaDeviceSandboxExtensions.cpp */; }; > 076E884E1A13CADF005E90FC /* APIContextMenuClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 076E884D1A13CADF005E90FC /* APIContextMenuClient.h */; }; >+ 0772811D21234FF600C8EF2E /* UserMediaPermissionRequestManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A410F4319AF7B27002EBAB5 /* UserMediaPermissionRequestManager.h */; }; > 07A5EBBB1C7BA43E00B9CA69 /* WKFrameHandleRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A5EBB91C7BA43E00B9CA69 /* WKFrameHandleRef.cpp */; }; > 07A5EBBC1C7BA43E00B9CA69 /* WKFrameHandleRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 07A5EBBA1C7BA43E00B9CA69 /* WKFrameHandleRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0E97D74D200E900400BF6643 /* SafeBrowsingSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E97D74C200E8FF300BF6643 /* SafeBrowsingSPI.h */; }; >@@ -9420,6 +9421,7 @@ > CD491B131E73482100009066 /* UserMediaCaptureManagerProxy.h in Headers */, > CD491B181E73525500009066 /* UserMediaCaptureManagerProxyMessages.h in Headers */, > 07297F9F1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.h in Headers */, >+ 0772811D21234FF600C8EF2E /* UserMediaPermissionRequestManager.h in Headers */, > 4A3CC18B19B0640F00D14AEF /* UserMediaPermissionRequestManagerProxy.h in Headers */, > 4A3CC18D19B0641900D14AEF /* UserMediaPermissionRequestProxy.h in Headers */, > 074E75FE1DF2211900D318EC /* UserMediaProcessManager.h in Headers */, >diff --git a/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp b/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp >index 9ccace0577c7fbc8ff5706bdfad93e437cc6e1f3..5bb4e85bb600a84a5f98a69b200e777cdadbcc22 100644 >--- a/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp >+++ b/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -40,6 +40,8 @@ namespace WebKit { > > using namespace WebCore; > >+static WebCore::ActivityState::Flags focusedActiveWindow = WebCore::ActivityState::IsFocused | WebCore::ActivityState::WindowIsActive; >+ > static uint64_t generateRequestID() > { > static uint64_t uniqueRequestID = 1; >@@ -53,6 +55,8 @@ UserMediaPermissionRequestManager::UserMediaPermissionRequestManager(WebPage& pa > > UserMediaPermissionRequestManager::~UserMediaPermissionRequestManager() > { >+ if (m_monitoringActivityStateChange) >+ m_page.corePage()->removeActivityStateChangeObserver(*this); > for (auto& sandboxExtension : m_userMediaDeviceSandboxExtensions) > sandboxExtension.value->revoke(); > } >@@ -222,6 +226,77 @@ void UserMediaPermissionRequestManager::revokeUserMediaDeviceSandboxExtensions(c > } > } > >+UserMediaClient::DeviceChangeObserverToken UserMediaPermissionRequestManager::addDeviceChangeObserver(WTF::Function<void()>&& observer) >+{ >+ auto identifier = generateObjectIdentifier<WebCore::UserMediaClient::DeviceChangeObserverTokenType>(); >+ m_deviceChangeObserverMap.add(identifier, WTFMove(observer)); >+ >+ if (!m_monitoringDeviceChange) { >+ m_monitoringDeviceChange = true; >+ m_page.send(Messages::WebPageProxy::BeginMonitoringCaptureDevices()); >+ } >+ return identifier; >+} >+ >+void UserMediaPermissionRequestManager::removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken token) >+{ >+ bool wasRemoved = m_deviceChangeObserverMap.remove(token); >+ ASSERT_UNUSED(wasRemoved, wasRemoved); >+} >+ >+void UserMediaPermissionRequestManager::captureDevicesChanged(DeviceAccessState accessState) >+{ >+ // When new media input and/or output devices are made available, or any available input and/or >+ // output device becomes unavailable, the User Agent MUST run the following steps in browsing >+ // contexts where at least one of the following criteria are met, but in no other contexts: >+ >+ // * The permission state of the "device-info" permission is "granted", >+ // * any of the input devices are attached to an active MediaStream in the browsing context, or >+ // * the active document is fully active and has focus. >+ >+ bool isActive = (m_page.corePage()->activityState() & focusedActiveWindow) == focusedActiveWindow; >+ if (!isActive && accessState == DeviceAccessState::NoAccess) { >+ if (!isActive) { >+ if (!m_monitoringActivityStateChange) { >+ m_monitoringActivityStateChange = true; >+ m_page.corePage()->addActivityStateChangeObserver(*this); >+ } >+ m_pendingDeviceChangeEvent = true; >+ m_accessStateWhenDevicesChanged = accessState; >+ } >+ return; >+ } >+ >+ auto identifiers = m_deviceChangeObserverMap.keys(); >+ for (auto& identifier : identifiers) { >+ auto iterator = m_deviceChangeObserverMap.find(identifier); >+ if (iterator != m_deviceChangeObserverMap.end()) >+ (iterator->value)(); >+ } >+} >+ >+void UserMediaPermissionRequestManager::activityStateDidChange(WebCore::ActivityState::Flags oldActivityState, WebCore::ActivityState::Flags newActivityState) >+{ >+ if ((newActivityState & focusedActiveWindow) != focusedActiveWindow) >+ return; >+ >+ RunLoop::main().dispatch([this, weakThis = makeWeakPtr(*this)]() mutable { >+ if (!weakThis || !m_monitoringActivityStateChange) >+ return; >+ >+ m_monitoringActivityStateChange = false; >+ m_page.corePage()->removeActivityStateChangeObserver(*this); >+ }); >+ >+ if (!m_pendingDeviceChangeEvent) >+ return; >+ >+ m_pendingDeviceChangeEvent = false; >+ auto accessState = m_accessStateWhenDevicesChanged; >+ m_accessStateWhenDevicesChanged = DeviceAccessState::NoAccess; >+ captureDevicesChanged(accessState); >+} >+ > } // namespace WebKit > > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h b/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h >index a7efc8adeaaee50905ac40a785255e8f6f8b4140..824f7d3f9d87ce4dffc6e5bced2182fa0a6901e5 100644 >--- a/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h >+++ b/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -24,6 +24,7 @@ > > #include "MediaDeviceSandboxExtensions.h" > #include "SandboxExtension.h" >+#include <WebCore/ActivityStateChangeObserver.h> > #include <WebCore/MediaCanStartListener.h> > #include <WebCore/MediaConstraints.h> > #include <WebCore/MediaDevicesEnumerationRequest.h> >@@ -37,8 +38,9 @@ namespace WebKit { > > class WebPage; > >-class UserMediaPermissionRequestManager >- : private WebCore::MediaCanStartListener { >+enum class DeviceAccessState { NoAccess, SessionAccess, PersistentAccess }; >+ >+class UserMediaPermissionRequestManager : public CanMakeWeakPtr<UserMediaPermissionRequestManager>, private WebCore::MediaCanStartListener, private WebCore::ActivityStateChangeObserver { > public: > explicit UserMediaPermissionRequestManager(WebPage&); > ~UserMediaPermissionRequestManager(); >@@ -55,11 +57,19 @@ public: > void grantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions&&); > void revokeUserMediaDeviceSandboxExtensions(const Vector<String>&); > >+ WebCore::UserMediaClient::DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&); >+ void removeDeviceChangeObserver(WebCore::UserMediaClient::DeviceChangeObserverToken); >+ >+ void captureDevicesChanged(DeviceAccessState); >+ > private: > void sendUserMediaRequest(WebCore::UserMediaRequest&); > > // WebCore::MediaCanStartListener >- void mediaCanStart(WebCore::Document&) override; >+ void mediaCanStart(WebCore::Document&) final; >+ >+ // WebCore::ActivityStateChangeObserver >+ void activityStateDidChange(WebCore::ActivityState::Flags oldActivityState, WebCore::ActivityState::Flags newActivityState) final; > > void removeMediaRequestFromMaps(WebCore::UserMediaRequest&); > >@@ -73,10 +83,29 @@ private: > HashMap<RefPtr<WebCore::MediaDevicesEnumerationRequest>, uint64_t> m_mediaDevicesEnumerationRequestToIDMap; > > HashMap<String, RefPtr<SandboxExtension>> m_userMediaDeviceSandboxExtensions; >+ >+ HashMap<WebCore::UserMediaClient::DeviceChangeObserverToken, WTF::Function<void()>> m_deviceChangeObserverMap; >+ DeviceAccessState m_accessStateWhenDevicesChanged { DeviceAccessState::NoAccess }; >+ bool m_monitoringDeviceChange { false }; >+ bool m_pendingDeviceChangeEvent { false }; >+ bool m_monitoringActivityStateChange { false }; > }; > > } // namespace WebKit > >+namespace WTF { >+ >+template<> struct EnumTraits<WebKit::DeviceAccessState> { >+ using values = EnumValues< >+ WebKit::DeviceAccessState, >+ WebKit::DeviceAccessState::NoAccess, >+ WebKit::DeviceAccessState::SessionAccess, >+ WebKit::DeviceAccessState::PersistentAccess >+ >; >+}; >+ >+} // namespace WTF >+ > #endif // ENABLE(MEDIA_STREAM) > > #endif // UserMediaPermissionRequestManager_h >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp >index 6f605742eec304202a6404b535bca7c5559b4fd1..0b06d639299db54f74c8a026d023a069970d0ee3 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -62,6 +62,16 @@ void WebUserMediaClient::cancelMediaDevicesEnumerationRequest(MediaDevicesEnumer > m_page.userMediaPermissionRequestManager().cancelMediaDevicesEnumeration(request); > } > >+WebUserMediaClient::DeviceChangeObserverToken WebUserMediaClient::addDeviceChangeObserver(WTF::Function<void()>&& observer) >+{ >+ return m_page.userMediaPermissionRequestManager().addDeviceChangeObserver(WTFMove(observer)); >+} >+ >+void WebUserMediaClient::removeDeviceChangeObserver(DeviceChangeObserverToken token) >+{ >+ m_page.userMediaPermissionRequestManager().removeDeviceChangeObserver(token); >+} >+ > } // namespace WebKit; > > #endif // MEDIA_STREAM >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h >index a6e313262d5ba7c4baf43bd304f3d8698094f36c..10930453ce797edd90de76f0354b9a1d406f2e6e 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2014 Igalia S.L. >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public >@@ -42,6 +42,9 @@ private: > void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&) final; > void cancelMediaDevicesEnumerationRequest(WebCore::MediaDevicesEnumerationRequest&) final; > >+ DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&) final; >+ void removeDeviceChangeObserver(DeviceChangeObserverToken) final; >+ > void initializeFactories(); > > WebPage& m_page; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index 51143a32db4099e6fff5a58c04b5a0f7784778e2..a41ed0e30a34b6adc14bd29ee8e5db2e3604b53e 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -3757,6 +3757,12 @@ void WebPage::didCompleteMediaDeviceEnumeration(uint64_t userMediaID, const Vect > { > m_userMediaPermissionRequestManager->didCompleteMediaDeviceEnumeration(userMediaID, devices, WTFMove(deviceIdentifierHashSalt), originHasPersistentAccess); > } >+ >+void WebPage::captureDevicesChanged(DeviceAccessState accessState) >+{ >+ m_userMediaPermissionRequestManager->captureDevicesChanged(accessState); >+} >+ > #if ENABLE(SANDBOX_EXTENSIONS) > void WebPage::grantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions&& extensions) > { >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h >index 408addd08e3c29829625274789c9eb591171451e..7136c1168ce13e25ad365f037f46b8b70d3f3e5d 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -228,6 +228,7 @@ class WebTouchEvent; > class WebCredentialsMessenger; > class RemoteLayerTreeTransaction; > >+enum class DeviceAccessState; > enum FindOptions : uint16_t; > enum class DragControllerAction; > >@@ -565,6 +566,7 @@ public: > #if ENABLE(MEDIA_STREAM) > UserMediaPermissionRequestManager& userMediaPermissionRequestManager() { return *m_userMediaPermissionRequestManager; } > void prepareToSendUserMediaPermissionRequest(); >+ void captureDevicesChanged(DeviceAccessState); > #endif > > void elementDidFocus(WebCore::Node*); >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >index 1c44d77e6524d636623e4246f256a5716b1c0379..cd3a5f830fdd6efa550b692417d16e040783a6ad 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >@@ -319,6 +319,7 @@ messages -> WebPage LegacyReceiver { > UserMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice audioDevice, WebCore::CaptureDevice videoDevice, String mediaDeviceIdentifierHashSalt) > UserMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint) > DidCompleteMediaDeviceEnumeration(uint64_t userMediaID, Vector<WebCore::CaptureDevice> devices, String mediaDeviceIdentifierHashSalt, bool hasPersistentAccess) >+ CaptureDevicesChanged(enum WebKit::DeviceAccessState accessState) > #if ENABLE(SANDBOX_EXTENSIONS) > GrantUserMediaDeviceSandboxExtensions(WebKit::MediaDeviceSandboxExtensions sandboxExtensions) > RevokeUserMediaDeviceSandboxExtensions(Vector<String> sandboxExtensionIDs) >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index bff88267835d9debaeb8c2fb1b30357da3079d75..be4a03368d16420dacec82824d3f456d2fe32ba7 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-08-15 Eric Carlson <eric.carlson@apple.com> >+ >+ [MediaStream] Move capture device monitoring to WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188521 >+ <rdar://problem/43251787> >+ >+ Reviewed by Youenn Fablet. >+ >+ * fast/mediastream/device-change-event-2-expected.txt: Updated. >+ * fast/mediastream/device-change-event-2.html: Updated. >+ > 2018-08-15 Per Arne Vollan <pvollan@apple.com> > > Layout Test editing/input/press-tab-during-ime-composition.html is failing >diff --git a/LayoutTests/fast/mediastream/device-change-event-2-expected.txt b/LayoutTests/fast/mediastream/device-change-event-2-expected.txt >index 64c6b61076faaa3de4f8168f7969cf10f607a69d..8dcf526fd60245546701b67a6fe9b2c90e8750be 100644 >--- a/LayoutTests/fast/mediastream/device-change-event-2-expected.txt >+++ b/LayoutTests/fast/mediastream/device-change-event-2-expected.txt >@@ -1,3 +1,6 @@ > > PASS 'devicechange' event fired when device list changes >+PASS 'devicechange' events fired quickly are coalesced >+PASS 'devicechange' event is not fired when the document doesn't has focus or permission to capture >+PASS 'devicechange' event is fired when the document doesn't has focus but has permission to capture > >diff --git a/LayoutTests/fast/mediastream/device-change-event-2.html b/LayoutTests/fast/mediastream/device-change-event-2.html >index 43d5f2bdfedd91ecbd23fc71b83571e0707b255b..614b8d1109dc790299bdbb708becf6ab47939aa5 100644 >--- a/LayoutTests/fast/mediastream/device-change-event-2.html >+++ b/LayoutTests/fast/mediastream/device-change-event-2.html >@@ -6,16 +6,25 @@ > <script src="../../resources/testharness.js"></script> > <script src="../../resources/testharnessreport.js"></script> > <script> >- let deviceIds = []; >- promise_test(async (test) => { >+ let stream = null; >+ >+ let setup = async (test) => { > if (!window.testRunner) > return Promise.reject("test requires internal API"); > > test.add_cleanup(() => { testRunner.resetMockMediaDevices(); }); > > testRunner.setUserMediaPermission(true); >+ >+ stream = null; >+ } >+ >+ promise_test(async (test) => { >+ >+ await setup(test); > >- await navigator.mediaDevices.getUserMedia({ audio:true, video:true }); >+ await navigator.mediaDevices.getUserMedia({ audio:true, video:true }) >+ .then(s => stream = s) > > let devices = await navigator.mediaDevices.enumerateDevices(); > >@@ -29,7 +38,7 @@ > await new Promise((resolve, reject) => { > navigator.mediaDevices.ondevicechange = resolve; > setTimeout(() => { >- console.log("event 1 taking a long time"); >+ console.log("event 1 took too long"); > resolve(); > }, 5000); > testRunner.addMockCameraDevice("id1", "my camera"); >@@ -41,7 +50,7 @@ > await new Promise((resolve, reject) => { > navigator.mediaDevices.ondevicechange = resolve; > setTimeout(() => { >- console.log("event 2 taking a long time"); >+ console.log("event 2 took too long"); > resolve(); > }, 5000); > testRunner.addMockMicrophoneDevice("id2", "my mic"); >@@ -51,6 +60,102 @@ > assert_equals(devices[0].label, "my mic"); > > }, "'devicechange' event fired when device list changes"); >+ >+ promise_test(async (test) => { >+ >+ await setup(test); >+ >+ let eventCount = 0; >+ await new Promise((resolve, reject) => { >+ navigator.mediaDevices.ondevicechange = (evt) => { >+ ++eventCount; >+ setTimeout(() => { >+ resolve(); >+ }, 500); >+ } >+ >+ setTimeout(() => { >+ console.log("navigator.mediaDevices.ondevicechange took too long"); >+ resolve(); >+ }, 4000); >+ >+ testRunner.addMockMicrophoneDevice("id4", "microphone 3"); >+ testRunner.addMockMicrophoneDevice("id5", "microphone 4"); >+ }); >+ assert_equals(eventCount, 1, "one event fired"); >+ >+ }, "'devicechange' events fired quickly are coalesced"); >+ >+ >+ promise_test(async (test) => { >+ >+ await setup(test); >+ >+ await new Promise((resolve, reject) => { >+ let timeout = setTimeout(() => { >+ console.log("window.onblur took too long"); >+ resolve(); >+ }, 5000); >+ >+ window.onblur = () => { >+ clearTimeout(timeout); >+ resolve(); >+ } >+ >+ internals.setPageIsFocusedAndActive(false); >+ }); >+ >+ await new Promise((resolve, reject) => { >+ assert_false(document.hasFocus(), "document.hasFocus()"); >+ >+ navigator.mediaDevices.ondevicechange = () => { >+ assert_true(document.hasFocus(), "devicechange should only fire when the document is focused and active"); >+ resolve(); >+ }; >+ >+ setTimeout(() => { >+ internals.setPageIsFocusedAndActive(true); >+ }, 200); >+ >+ testRunner.addMockMicrophoneDevice("id3", "microphone 2"); >+ }); >+ >+ }, "'devicechange' event is not fired when the document doesn't has focus or permission to capture"); >+ >+ promise_test(async (test) => { >+ >+ await setup(test); >+ >+ await navigator.mediaDevices.getUserMedia({ audio:true, video:true }) >+ .then(s => stream = s); >+ >+ await new Promise((resolve, reject) => { >+ let timeout = setTimeout(() => { >+ console.log("window.onblur took too long"); >+ resolve(); >+ }, 5000); >+ >+ window.onblur = () => { >+ clearTimeout(timeout); >+ resolve(); >+ } >+ >+ internals.setPageIsFocusedAndActive(false); >+ }); >+ >+ await new Promise((resolve, reject) => { >+ assert_false(document.hasFocus(), "document.hasFocus()"); >+ >+ navigator.mediaDevices.ondevicechange = () => { >+ assert_false(document.hasFocus(), "devicechange should fire when the document is not focused but can capture"); >+ resolve(); >+ }; >+ >+ testRunner.addMockMicrophoneDevice("id3", "microphone 2"); >+ }); >+ >+ }, "'devicechange' event is fired when the document doesn't has focus but has permission to capture"); >+ > </script> > </head> > <body>
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 188521
:
347035
|
347229
|
347366
|
347382
|
347496
|
347501