[MediaStream] MediaDeviceInfo.label must be empty in some situations
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Dec 2015 22:51:28 +0000 (22:51 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Dec 2015 22:51:28 +0000 (22:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152000

Reviewed by Brent Fulgham.

Source/WebCore:

No new tests, updated fast/mediastream/MediaDevices-enumerateDevices.html.

* Modules/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::getSourcesInfo): TrackSourceInfo constructor takes persistent ID.

* Modules/mediastream/MediaDevicesRequest.cpp:
(WebCore::MediaDevicesRequest::start): If Document had an active stream track, don't bother
  checking for a persistent permission to access devices.
(WebCore::MediaDevicesRequest::didCompleteCheck): m_hasUserMediaPermission -> m_canShowLabels.
(WebCore::MediaDevicesRequest::getTrackSources): New, factored out of didCompleteCheck so it
  can be called when we don't need to check permissions.
(WebCore::MediaDevicesRequest::didCompleteRequest): m_hasUserMediaPermission -> m_canShowLabels.
* Modules/mediastream/MediaDevicesRequest.h:

* Modules/mediastream/MediaStream.cpp:
(WebCore::MediaStream::MediaStream): Call setIsActive. Register new stream with MediaStreamRegistry.
(WebCore::MediaStream::~MediaStream): Unregister stream with MediaStreamRegistry.
(WebCore::MediaStream::setIsActive): New. Set m_isActive and call Document if stream is active.
(WebCore::MediaStream::scheduleActiveStateChange): Call setIsActive.
(WebCore::MediaStream::registry): MediaStreamRegistry::registry -> MediaStreamRegistry::shared.
(WebCore::mediaStreams): Deleted. Drive-by cleanup: moved list of all streams to MediaStreamRegistry.
(WebCore::registerMediaStream): Ditto.
(WebCore::unRegisterMediaStream): Ditto.
(WebCore::MediaStream::lookUp): Ditto.
(WebCore::MediaStream::setRegistry): Ditto.
* Modules/mediastream/MediaStream.h:

* Modules/mediastream/MediaStreamRegistry.cpp:
(WebCore::MediaStreamRegistry::shared): Renamed from "registry".
(WebCore::MediaStreamRegistry::MediaStreamRegistry):
(WebCore::MediaStreamRegistry::lookUp): Moved here from MediaStream.
(WebCore::mediaStreams): Ditto.
(WebCore::MediaStreamRegistry::registerStream): Ditto.
(WebCore::MediaStreamRegistry::unregisterStream): Ditto.
(WebCore::MediaStreamRegistry::registry): Deleted.
* Modules/mediastream/MediaStreamRegistry.h:

* dom/Document.h:
(WebCore::Document::setHasActiveMediaStreamTrack): New, set m_hasHadActiveMediaStreamTrack.
(WebCore::Document::hasHadActiveMediaStreamTrack): New, return m_hasHadActiveMediaStreamTrack.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::loadResource): MediaStream::lookUp -> MediaStreamRegistry::shared().lookUp.

* platform/mediastream/MediaStreamTrackSourcesRequestClient.h:
(WebCore::TrackSourceInfo::create): Take track persistent ID.
(WebCore::TrackSourceInfo::persistentId): New.
(WebCore::TrackSourceInfo::TrackSourceInfo): Take track persistent ID.

* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::sourceWithUID): TrackSourceInfo::create takes persistent ID.

* platform/mock/MockRealtimeMediaSource.cpp:
(WebCore::MockRealtimeMediaSource::trackSourceWithUID): Ditto.

* platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.cpp:
(WebCore::RealtimeMediaSourceCenterMac::sourceWithUID): TrackSourceInfo::create takes persistent ID.

Tools:

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::setUserMediaPermission):
(WTR::InjectedBundle::setUserMediaPermissionForOrigin): New.
* WebKitTestRunner/InjectedBundle/InjectedBundle.h:

* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setUserMediaPermissionForOrigin): New.
* WebKitTestRunner/InjectedBundle/TestRunner.h:

* WebKitTestRunner/TestController.cpp:
(WTR::TestController::setUserMediaPermissionForOrigin):
(WTR::TestController::handleCheckOfUserMediaPermissionForOrigin): Add NULL check.
(WTR::TestController::decidePolicyForUserMediaPermissionRequestIfPossible): Don't add
  persistent permission for origin, that can be done from script now.
* WebKitTestRunner/TestController.h:

* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle): Add support for
  SetUserMediaPermissionForOrigin.

LayoutTests:

* fast/mediastream/MediaDevices-enumerateDevices-expected.txt:
* fast/mediastream/MediaDevices-enumerateDevices.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194397 268f45cc-cd09-0410-ab3c-d52691b4dbfc

26 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/mediastream/MediaDevices-enumerateDevices-expected.txt
LayoutTests/fast/mediastream/MediaDevices-enumerateDevices.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp
Source/WebCore/Modules/mediastream/MediaDevicesRequest.cpp
Source/WebCore/Modules/mediastream/MediaDevicesRequest.h
Source/WebCore/Modules/mediastream/MediaStream.cpp
Source/WebCore/Modules/mediastream/MediaStream.h
Source/WebCore/Modules/mediastream/MediaStreamRegistry.cpp
Source/WebCore/Modules/mediastream/MediaStreamRegistry.h
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/platform/mediastream/MediaStreamTrackSourcesRequestClient.h
Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp
Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp
Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index 9adfb00..94601ea 100644 (file)
@@ -1,3 +1,13 @@
+2015-12-23  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] MediaDeviceInfo.label must be empty in some situations
+        https://bugs.webkit.org/show_bug.cgi?id=152000
+
+        Reviewed by Brent Fulgham.
+
+        * fast/mediastream/MediaDevices-enumerateDevices-expected.txt:
+        * fast/mediastream/MediaDevices-enumerateDevices.html:
+
 2015-12-23  Andy VanWagoner  <andy@instructure.com>
 
         [INTL] Implement DateTime Format Functions
index 7789df9..b40da44 100644 (file)
@@ -7,7 +7,7 @@ PASS navigator.mediaDevices is an instance of Object
 PASS navigator.mediaDevices.enumerateDevices is an instance of Function
 
 
-*** Calling mediaDevices.enumerateDevices when persistent access HAS NOT been granted
+*** Calling mediaDevices.enumerateDevices without persistent access, and without a media stream track
 
 PASS captureDevices.length is non-zero.
 
@@ -24,7 +24,24 @@ PASS captureDevice.label is ""
 PASS captureDevice.groupId is non-null.
 
 
-*** Calling mediaDevices.enumerateDevices when persistent access HAS been granted
+*** Calling mediaDevices.enumerateDevices without persistent access, and without a media stream track
+
+PASS captureDevices.length is non-zero.
+
+PASS captureDevice.kind is non-null.
+PASS captureDevice.deviceId is non-null.
+PASS captureDevice.label is non-null.
+PASS captureDevice.label is not ""
+PASS captureDevice.groupId is non-null.
+
+PASS captureDevice.kind is non-null.
+PASS captureDevice.deviceId is non-null.
+PASS captureDevice.label is non-null.
+PASS captureDevice.label is not ""
+PASS captureDevice.groupId is non-null.
+
+
+*** Calling mediaDevices.enumerateDevices without persistent access, with a media stream track
 
 PASS captureDevices.length is non-zero.
 
index b5a66f3..fdcf9b5 100644 (file)
@@ -20,7 +20,6 @@
 
             function enumerate(next)
             {
-                debug(`<br>*** Calling mediaDevices.enumerateDevices when persistent access HAS ${havePermission ? "" : "NOT "}been granted<br>`);
                 navigator.mediaDevices.enumerateDevices()
                     .then(function(devices) {
                         captureDevices = devices;
                     });
             }
             
-            function grantPermission()
+            function createStream()
             {
                 if (window.testRunner) {
                     testRunner.setUserMediaPermission(true);
-                    navigator.mediaDevices
-                        .getUserMedia({audio:{}, video:{}})
-                        .then(function(stream) {
-                            havePermission = true;
-                            enumerate(null);                        
-                        })
-                        .catch(function(err) {
-                            testFailed(`mediaDevices.getUserMedia() failed with ${err.name}: ${err.message}`);
-                        });
+                    testRunner.setUserMediaPermissionForOrigin(false, document.location.href);
                 }
+
+                navigator.mediaDevices
+                    .getUserMedia({audio:{}, video:{}})
+                    .then(function(stream) {
+                        debug(`<br>*** Calling mediaDevices.enumerateDevices without persistent access, with a media stream track<br>`);
+                        havePermission = true;
+                        enumerate(null);                        
+                    })
+                    .catch(function(err) {
+                        testFailed(`mediaDevices.getUserMedia() failed with ${err.name}: ${err.message}`);
+                    });
+            }
+            
+            function grantPermission()
+            {
+                if (window.testRunner)
+                    testRunner.setUserMediaPermissionForOrigin(true, document.location.href);
+
+                debug(`<br>*** Calling mediaDevices.enumerateDevices without persistent access, and without a media stream track<br>`);
+                havePermission = true;
+                enumerate(createStream);
             }
 
             havePermission = false;
+            debug(`<br>*** Calling mediaDevices.enumerateDevices without persistent access, and without a media stream track<br>`);
             enumerate(grantPermission);
 
             window.successfullyParsed = true;
index 7bce609..0fd843a 100644 (file)
@@ -1,3 +1,68 @@
+2015-12-23  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] MediaDeviceInfo.label must be empty in some situations
+        https://bugs.webkit.org/show_bug.cgi?id=152000
+
+        Reviewed by Brent Fulgham.
+
+        No new tests, updated fast/mediastream/MediaDevices-enumerateDevices.html.
+
+        * Modules/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::getSourcesInfo): TrackSourceInfo constructor takes persistent ID.
+
+        * Modules/mediastream/MediaDevicesRequest.cpp:
+        (WebCore::MediaDevicesRequest::start): If Document had an active stream track, don't bother
+          checking for a persistent permission to access devices.
+        (WebCore::MediaDevicesRequest::didCompleteCheck): m_hasUserMediaPermission -> m_canShowLabels.
+        (WebCore::MediaDevicesRequest::getTrackSources): New, factored out of didCompleteCheck so it
+          can be called when we don't need to check permissions.
+        (WebCore::MediaDevicesRequest::didCompleteRequest): m_hasUserMediaPermission -> m_canShowLabels.
+        * Modules/mediastream/MediaDevicesRequest.h:
+
+        * Modules/mediastream/MediaStream.cpp:
+        (WebCore::MediaStream::MediaStream): Call setIsActive. Register new stream with MediaStreamRegistry.
+        (WebCore::MediaStream::~MediaStream): Unregister stream with MediaStreamRegistry.
+        (WebCore::MediaStream::setIsActive): New. Set m_isActive and call Document if stream is active.
+        (WebCore::MediaStream::scheduleActiveStateChange): Call setIsActive.
+        (WebCore::MediaStream::registry): MediaStreamRegistry::registry -> MediaStreamRegistry::shared.
+        (WebCore::mediaStreams): Deleted. Drive-by cleanup: moved list of all streams to MediaStreamRegistry.
+        (WebCore::registerMediaStream): Ditto.
+        (WebCore::unRegisterMediaStream): Ditto.
+        (WebCore::MediaStream::lookUp): Ditto.
+        (WebCore::MediaStream::setRegistry): Ditto.
+        * Modules/mediastream/MediaStream.h:
+
+        * Modules/mediastream/MediaStreamRegistry.cpp:
+        (WebCore::MediaStreamRegistry::shared): Renamed from "registry".
+        (WebCore::MediaStreamRegistry::MediaStreamRegistry):
+        (WebCore::MediaStreamRegistry::lookUp): Moved here from MediaStream.
+        (WebCore::mediaStreams): Ditto.
+        (WebCore::MediaStreamRegistry::registerStream): Ditto.
+        (WebCore::MediaStreamRegistry::unregisterStream): Ditto.
+        (WebCore::MediaStreamRegistry::registry): Deleted.
+        * Modules/mediastream/MediaStreamRegistry.h:
+
+        * dom/Document.h:
+        (WebCore::Document::setHasActiveMediaStreamTrack): New, set m_hasHadActiveMediaStreamTrack.
+        (WebCore::Document::hasHadActiveMediaStreamTrack): New, return m_hasHadActiveMediaStreamTrack.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::loadResource): MediaStream::lookUp -> MediaStreamRegistry::shared().lookUp.
+
+        * platform/mediastream/MediaStreamTrackSourcesRequestClient.h:
+        (WebCore::TrackSourceInfo::create): Take track persistent ID.
+        (WebCore::TrackSourceInfo::persistentId): New.
+        (WebCore::TrackSourceInfo::TrackSourceInfo): Take track persistent ID.
+
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::sourceWithUID): TrackSourceInfo::create takes persistent ID.
+
+        * platform/mock/MockRealtimeMediaSource.cpp:
+        (WebCore::MockRealtimeMediaSource::trackSourceWithUID): Ditto.
+
+        * platform/mediastream/openwebrtc/RealtimeMediaSourceOwr.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::sourceWithUID): TrackSourceInfo::create takes persistent ID.
+
 2015-12-23  Xabier Rodriguez Calvar  <calvaris@igalia.com>
 
         [Streams API] In RS during enqueuing error should be reported only if readable
index f68bcd8..bac95ca 100644 (file)
@@ -52,7 +52,7 @@ Vector<RefPtr<TrackSourceInfo>> CaptureDeviceManager::getSourcesInfo(const Strin
             continue;
 
         TrackSourceInfo::SourceKind trackSourceType = captureDevice.m_sourceType == RealtimeMediaSource::Video ? TrackSourceInfo::Video : TrackSourceInfo::Audio;
-        sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_sourceId, trackSourceType, captureDevice.m_localizedName, captureDevice.m_groupID));
+        sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_persistentDeviceID, captureDevice.m_sourceId, trackSourceType, captureDevice.m_localizedName, captureDevice.m_groupID));
     }
     LOG(Media, "CaptureDeviceManager::getSourcesInfo(%p), found %zu active devices", this, sourcesInfo.size());
     return sourcesInfo;
index ad8cc6b..c6a2086 100644 (file)
@@ -77,6 +77,15 @@ void MediaDevicesRequest::contextDestroyed()
 void MediaDevicesRequest::start()
 {
     m_protector = this;
+
+    if (Document* document = downcast<Document>(scriptExecutionContext())) {
+        m_canShowLabels = document->hasHadActiveMediaStreamTrack();
+        if (m_canShowLabels) {
+            getTrackSources();
+            return;
+        }
+    }
+
     m_permissionCheck = UserMediaPermissionCheck::create(*downcast<Document>(scriptExecutionContext()), *this);
     m_permissionCheck->start();
 }
@@ -86,8 +95,12 @@ void MediaDevicesRequest::didCompleteCheck(bool canAccess)
     m_permissionCheck->setClient(nullptr);
     m_permissionCheck = nullptr;
 
-    m_hasUserMediaPermission = canAccess;
+    m_canShowLabels = canAccess;
+    getTrackSources();
+}
 
+void MediaDevicesRequest::getTrackSources()
+{
     callOnMainThread([this] {
         RealtimeMediaSourceCenter::singleton().getMediaStreamTrackSources(this);
     });
@@ -105,7 +118,7 @@ void MediaDevicesRequest::didCompleteRequest(const TrackSourceInfoVector& captur
         TrackSourceInfo* trackInfo = device.get();
         String deviceType = trackInfo->kind() == TrackSourceInfo::SourceKind::Audio ? MediaDeviceInfo::audioInputType() : MediaDeviceInfo::videoInputType();
 
-        AtomicString label = m_hasUserMediaPermission ? trackInfo->label() : emptyAtom;
+        AtomicString label = m_canShowLabels ? trackInfo->label() : emptyAtom;
         deviceInfo.append(MediaDeviceInfo::create(m_scriptExecutionContext, label, trackInfo->id(), trackInfo->groupId(), deviceType));
     }
 
index 491162c..ffcc55e 100644 (file)
@@ -59,6 +59,8 @@ public:
 private:
     MediaDevicesRequest(ScriptExecutionContext*, MediaDevices::EnumerateDevicesPromise&&);
 
+    void getTrackSources();
+
     // MediaStreamTrackSourcesRequestClient
     const String& requestOrigin() const final;
     void didCompleteRequest(const TrackSourceInfoVector&) final;
@@ -73,7 +75,7 @@ private:
     RefPtr<MediaDevicesRequest> m_protector;
     RefPtr<UserMediaPermissionCheck> m_permissionCheck;
 
-    bool m_hasUserMediaPermission { false };
+    bool m_canShowLabels { false };
 };
 
 } // namespace WebCore
index 5059a9e..2d7489b 100644 (file)
@@ -30,6 +30,7 @@
 
 #if ENABLE(MEDIA_STREAM)
 
+#include "Document.h"
 #include "Event.h"
 #include "ExceptionCode.h"
 #include "MediaStreamRegistry.h"
 
 namespace WebCore {
 
-static Vector<MediaStream*>& mediaStreams()
-{
-    static NeverDestroyed<Vector<MediaStream*>> streams;
-    return streams;
-}
-
-static void registerMediaStream(MediaStream* stream)
-{
-    mediaStreams().append(stream);
-}
-
-static void unRegisterMediaStream(MediaStream* stream)
-{
-    Vector<MediaStream*>& allStreams = mediaStreams();
-    size_t pos = allStreams.find(stream);
-    if (pos != notFound)
-        allStreams.remove(pos);
-}
-
-MediaStream* MediaStream::lookUp(const MediaStreamPrivate& privateStream)
-{
-    Vector<MediaStream*>& allStreams = mediaStreams();
-    for (auto& stream : allStreams) {
-        if (stream->m_private == &privateStream)
-            return stream;
-    }
-
-    return nullptr;
-}
-
-static URLRegistry* s_registry;
-
-void MediaStream::setRegistry(URLRegistry& registry)
-{
-    ASSERT(!s_registry);
-    s_registry = &registry;
-}
-
-MediaStream* MediaStream::lookUp(const URL& url)
-{
-    if (!s_registry)
-        return nullptr;
-
-    return static_cast<MediaStream*>(s_registry->lookup(url.string()));
-}
-
 Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context)
 {
     return MediaStream::create(context, MediaStreamPrivate::create(Vector<RefPtr<MediaStreamTrackPrivate>>()));
@@ -124,20 +79,20 @@ MediaStream::MediaStream(ScriptExecutionContext& context, const MediaStreamTrack
     }
 
     m_private = MediaStreamPrivate::create(trackPrivates);
-    m_isActive = m_private->active();
+    setIsActive(m_private->active());
     m_private->addObserver(*this);
-    registerMediaStream(this);
+    MediaStreamRegistry::shared().registerStream(*this);
 }
 
 MediaStream::MediaStream(ScriptExecutionContext& context, RefPtr<MediaStreamPrivate>&& streamPrivate)
     : ContextDestructionObserver(&context)
     , m_private(streamPrivate)
-    , m_isActive(m_private->active())
     , m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
 {
     ASSERT(m_private);
+    setIsActive(m_private->active());
     m_private->addObserver(*this);
-    registerMediaStream(this);
+    MediaStreamRegistry::shared().registerStream(*this);
 
     for (auto& trackPrivate : m_private->tracks()) {
         RefPtr<MediaStreamTrack> track = MediaStreamTrack::create(context, *trackPrivate);
@@ -148,7 +103,7 @@ MediaStream::MediaStream(ScriptExecutionContext& context, RefPtr<MediaStreamPriv
 
 MediaStream::~MediaStream()
 {
-    unRegisterMediaStream(this);
+    MediaStreamRegistry::shared().unregisterStream(*this);
     m_private->removeObserver(*this);
     for (auto& track : m_trackSet.values())
         track->removeObserver(this);
@@ -276,6 +231,16 @@ bool MediaStream::internalRemoveTrack(RefPtr<MediaStreamTrack>&& track, StreamMo
     return true;
 }
 
+void MediaStream::setIsActive(bool active)
+{
+    m_isActive = active;
+    if (!active)
+        return;
+
+    if (Document* document = downcast<Document>(scriptExecutionContext()))
+        document->setHasActiveMediaStreamTrack();
+}
+
 void MediaStream::scheduleActiveStateChange()
 {
     bool active = false;
@@ -285,10 +250,11 @@ void MediaStream::scheduleActiveStateChange()
             break;
         }
     }
+
     if (m_isActive == active)
         return;
 
-    m_isActive = active;
+    setIsActive(active);
 
     const AtomicString& eventName = m_isActive ? eventNames().inactiveEvent : eventNames().activeEvent;
     m_scheduledActivityEvents.append(Event::create(eventName, false, false));
@@ -308,7 +274,7 @@ void MediaStream::activityEventTimerFired()
 
 URLRegistry& MediaStream::registry() const
 {
-    return MediaStreamRegistry::registry();
+    return MediaStreamRegistry::shared();
 }
 
 MediaStreamTrackVector MediaStream::trackVectorForType(RealtimeMediaSource::Type filterType) const
index 1a45647..cd253da 100644 (file)
@@ -52,11 +52,6 @@ public:
         virtual void didAddOrRemoveTrack() = 0;
     };
 
-    static void setRegistry(URLRegistry&);
-    static MediaStream* lookUp(const URL&);
-
-    static MediaStream* lookUp(const MediaStreamPrivate&);
-
     static Ref<MediaStream> create(ScriptExecutionContext&);
     static Ref<MediaStream> create(ScriptExecutionContext&, MediaStream*);
     static Ref<MediaStream> create(ScriptExecutionContext&, const MediaStreamTrackVector&);
@@ -119,6 +114,7 @@ private:
 
     void scheduleActiveStateChange();
     void activityEventTimerFired();
+    void setIsActive(bool);
 
     MediaStreamTrackVector trackVectorForType(RealtimeMediaSource::Type) const;
 
index ef4ec96..f4b8eb1 100644 (file)
 
 #if ENABLE(MEDIA_STREAM)
 
-#include "URL.h"
 #include "MediaStream.h"
+#include "URL.h"
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
 
 namespace WebCore {
 
-MediaStreamRegistry& MediaStreamRegistry::registry()
+MediaStreamRegistry& MediaStreamRegistry::shared()
 {
     // Since WebWorkers cannot obtain MediaSource objects, we should be on the main thread.
     ASSERT(isMainThread());
@@ -64,7 +64,41 @@ URLRegistrable* MediaStreamRegistry::lookup(const String& url) const
 
 MediaStreamRegistry::MediaStreamRegistry()
 {
-    MediaStream::setRegistry(*this);
+}
+
+MediaStream* MediaStreamRegistry::lookUp(const URL& url) const
+{
+    return static_cast<MediaStream*>(lookup(url.string()));
+}
+
+static Vector<MediaStream*>& mediaStreams()
+{
+    static NeverDestroyed<Vector<MediaStream*>> streams;
+    return streams;
+}
+
+void MediaStreamRegistry::registerStream(MediaStream& stream)
+{
+    mediaStreams().append(&stream);
+}
+
+void MediaStreamRegistry::unregisterStream(MediaStream& stream)
+{
+    Vector<MediaStream*>& allStreams = mediaStreams();
+    size_t pos = allStreams.find(&stream);
+    if (pos != notFound)
+        allStreams.remove(pos);
+}
+
+MediaStream* MediaStreamRegistry::lookUp(const MediaStreamPrivate& privateStream) const
+{
+    Vector<MediaStream*>& allStreams = mediaStreams();
+    for (auto& stream : allStreams) {
+        if (stream->privateStream() == &privateStream)
+            return stream;
+    }
+
+    return nullptr;
 }
 
 } // namespace WebCore
index fdcd444..3604610 100644 (file)
 
 namespace WebCore {
 
-class URL;
 class MediaStream;
+class MediaStreamPrivate;
+class URL;
 
 class MediaStreamRegistry final : public URLRegistry {
 public:
     friend class NeverDestroyed<MediaStreamRegistry>;
 
     // Returns a single instance of MediaStreamRegistry.
-    static MediaStreamRegistry& registry();
+    static MediaStreamRegistry& shared();
 
     // Registers a blob URL referring to the specified stream data.
     virtual void registerURL(SecurityOrigin*, const URL&, URLRegistrable*) override;
@@ -51,6 +52,12 @@ public:
 
     virtual URLRegistrable* lookup(const String&) const override;
 
+    void registerStream(MediaStream&);
+    void unregisterStream(MediaStream&);
+
+    MediaStream* lookUp(const URL&) const;
+    MediaStream* lookUp(const MediaStreamPrivate&) const;
+
 private:
     MediaStreamRegistry();
     HashMap<String, RefPtr<MediaStream>> m_mediaStreams;
index 34c1266..373df53 100644 (file)
@@ -1312,6 +1312,11 @@ public:
     void addViewportDependentPicture(HTMLPictureElement&);
     void removeViewportDependentPicture(HTMLPictureElement&);
 
+#if ENABLE(MEDIA_STREAM)
+    void setHasActiveMediaStreamTrack() { m_hasHadActiveMediaStreamTrack = true; }
+    bool hasHadActiveMediaStreamTrack() const { return m_hasHadActiveMediaStreamTrack; }
+#endif
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1780,6 +1785,10 @@ private:
     RefPtr<MediaSession> m_defaultMediaSession;
 #endif
     bool m_areDeviceMotionAndOrientationUpdatesSuspended { false };
+
+#if ENABLE(MEDIA_STREAM)
+    bool m_hasHadActiveMediaStreamTrack { false };
+#endif
 };
 
 inline void Document::notifyRemovePendingSheetIfNeeded()
index 577ab0c..3eaf1af 100644 (file)
@@ -1328,7 +1328,7 @@ void HTMLMediaElement::loadResource(const URL& initialURL, ContentType& contentT
 #if ENABLE(MEDIA_STREAM)
     if (!loadAttempted) {
         if (!m_mediaStreamSrcObject && url.protocolIs(mediaStreamBlobProtocol))
-            m_mediaStreamSrcObject = MediaStream::lookUp(url);
+            m_mediaStreamSrcObject = MediaStreamRegistry::shared().lookUp(url);
 
         if (m_mediaStreamSrcObject) {
             loadAttempted = true;
index 46c53ac..d18af07 100644 (file)
@@ -39,37 +39,41 @@ class TrackSourceInfo : public RefCounted<TrackSourceInfo> {
 public:
     enum SourceKind { Audio, Video };
 
-    static PassRefPtr<TrackSourceInfo> create(const AtomicString& id, SourceKind kind, const AtomicString& label)
+    static PassRefPtr<TrackSourceInfo> create(const AtomicString& persistentId, const AtomicString& id, SourceKind kind, const AtomicString& label)
     {
-        return adoptRef(new TrackSourceInfo(id, kind, label));
+        return adoptRef(new TrackSourceInfo(persistentId, id, kind, label));
     }
 
-    static Ref<TrackSourceInfo> create(const AtomicString& id, SourceKind kind, const AtomicString& label, const AtomicString& groupId)
+    static Ref<TrackSourceInfo> create(const AtomicString& persistentId, const AtomicString& id, SourceKind kind, const AtomicString& label, const AtomicString& groupId)
     {
-        return adoptRef(*new TrackSourceInfo(id, kind, label, groupId));
+        return adoptRef(*new TrackSourceInfo(persistentId, id, kind, label, groupId));
     }
 
     const AtomicString& id() const { return m_id; }
+    const AtomicString& persistentId() const { return m_persistentId; }
     const AtomicString& label() const { return m_label; }
     const AtomicString& groupId() const { return m_groupId; }
     SourceKind kind() const { return m_kind; }
 
 private:
-    TrackSourceInfo(const AtomicString& id, SourceKind kind, const AtomicString& label)
-        : m_id(id)
+    TrackSourceInfo(const AtomicString& persistentId, const AtomicString& id, SourceKind kind, const AtomicString& label)
+        : m_persistentId(persistentId)
+        , m_id(id)
         , m_kind(kind)
         , m_label(label)
     {
     }
 
-    TrackSourceInfo(const AtomicString& id, SourceKind kind, const AtomicString& label, const AtomicString& groupId)
-        : m_id(id)
+    TrackSourceInfo(const AtomicString& persistentId, const AtomicString& id, SourceKind kind, const AtomicString& label, const AtomicString& groupId)
+        : m_persistentId(persistentId)
+        , m_id(id)
         , m_kind(kind)
         , m_label(label)
         , m_groupId(groupId)
     {
     }
 
+    AtomicString m_persistentId;
     AtomicString m_id;
     SourceKind m_kind;
     AtomicString m_label;
@@ -84,7 +88,6 @@ public:
 
     virtual const String& requestOrigin() const = 0;
     virtual void didCompleteRequest(const TrackSourceInfoVector&) = 0;
-
 };
 
 
index 5c3064a..b49d1f6 100644 (file)
@@ -178,7 +178,7 @@ RefPtr<TrackSourceInfo> RealtimeMediaSourceCenterMac::sourceWithUID(const String
     RefPtr<RealtimeMediaSource> mediaSource = AVCaptureDeviceManager::singleton().sourceWithUID(UID, type, constraints);
     if (!mediaSource)
         return nullptr;
-    return TrackSourceInfo::create(mediaSource->id(), mediaSource->type() == RealtimeMediaSource::Type::Video ? TrackSourceInfo::SourceKind::Video : TrackSourceInfo::SourceKind::Audio, mediaSource->name());
+    return TrackSourceInfo::create(mediaSource->persistentID(), mediaSource->id(), mediaSource->type() == RealtimeMediaSource::Type::Video ? TrackSourceInfo::SourceKind::Video : TrackSourceInfo::SourceKind::Audio, mediaSource->name());
 }
 
 } // namespace WebCore
index cf584ad..4e762c4 100644 (file)
@@ -215,7 +215,7 @@ RefPtr<TrackSourceInfo> RealtimeMediaSourceCenterOwr::sourceWithUID(const String
 {
     for (auto& source : m_sourceMap.values()) {
         if (source->id() == UID)
-            return TrackSourceInfo::create(source->id(), source->type() == RealtimeMediaSource::Type::Video ? TrackSourceInfo::SourceKind::Video : TrackSourceInfo::SourceKind::Audio , source->name());
+            return TrackSourceInfo::create(source->persistentID(), source->id(), source->type() == RealtimeMediaSource::Type::Video ? TrackSourceInfo::SourceKind::Video : TrackSourceInfo::SourceKind::Audio , source->name());
     }
 
     return nullptr;
index 8ab3e7c..1a8b883 100644 (file)
@@ -73,10 +73,10 @@ RefPtr<TrackSourceInfo> MockRealtimeMediaSource::trackSourceWithUID(const String
     // FIXME: validate constraints.
 
     if (mockAudioSourcePersistentID() == id)
-        return TrackSourceInfo::create(mockAudioSourcePersistentID(), TrackSourceInfo::Audio, "Mock audio device");
+        return TrackSourceInfo::create(mockAudioSourcePersistentID(), id, TrackSourceInfo::Audio, "Mock audio device");
 
     if (mockVideoSourcePersistentID() == id)
-        return TrackSourceInfo::create(mockVideoSourcePersistentID(), TrackSourceInfo::Video, "Mock video device");
+        return TrackSourceInfo::create(mockVideoSourcePersistentID(), id, TrackSourceInfo::Video, "Mock video device");
     
     return nullptr;
 }
index 38bc9fb..1b75e94 100644 (file)
@@ -1,3 +1,31 @@
+2015-12-23  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] MediaDeviceInfo.label must be empty in some situations
+        https://bugs.webkit.org/show_bug.cgi?id=152000
+
+        Reviewed by Brent Fulgham.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::setUserMediaPermission):
+        (WTR::InjectedBundle::setUserMediaPermissionForOrigin): New.
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
+
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setUserMediaPermissionForOrigin): New.
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setUserMediaPermissionForOrigin):
+        (WTR::TestController::handleCheckOfUserMediaPermissionForOrigin): Add NULL check.
+        (WTR::TestController::decidePolicyForUserMediaPermissionRequestIfPossible): Don't add 
+          persistent permission for origin, that can be done from script now.
+        * WebKitTestRunner/TestController.h:
+
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): Add support for
+          SetUserMediaPermissionForOrigin.
+
 2015-12-23  Brent Fulgham  <bfulgham@apple.com>
 
         [Win] Unreviewed build fix: Recognize Windows 10 variants.
index 19f180e..a86202b 100644 (file)
@@ -179,6 +179,7 @@ interface TestRunner {
 
     // MediaStream
     void setUserMediaPermission(boolean value);
+    void setUserMediaPermissionForOrigin(boolean permission, DOMString url);
 
     // Audio testing.
     [PassContext] void setAudioResult(object data);
index a325881..72c0458 100644 (file)
@@ -526,6 +526,21 @@ void InjectedBundle::setUserMediaPermission(bool enabled)
     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
 }
 
+void InjectedBundle::setUserMediaPermissionForOrigin(bool permission, WKStringRef url)
+{
+    auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermissionForOrigin"));
+    WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
+
+    WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission"));
+    WKRetainPtr<WKBooleanRef> permissionWK(AdoptWK, WKBooleanCreate(permission));
+    WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get());
+
+    WKRetainPtr<WKStringRef> urlKeyWK(AdoptWK, WKStringCreateWithUTF8CString("url"));
+    WKDictionarySetItem(messageBody.get(), urlKeyWK.get(), url);
+
+    WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
+}
+
 void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive)
 {
     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCustomPolicyDelegate"));
index 8a1193a..0f0e1f1 100644 (file)
@@ -96,6 +96,7 @@ public:
 
     // MediaStream.
     void setUserMediaPermission(bool);
+    void setUserMediaPermissionForOrigin(bool permission, WKStringRef url);
 
     // Policy delegate.
     void setCustomPolicyDelegate(bool enabled, bool permissive);
index 8ebadd7..e3f8f56 100644 (file)
@@ -775,6 +775,12 @@ void TestRunner::setUserMediaPermission(bool enabled)
     InjectedBundle::singleton().setUserMediaPermission(enabled);
 }
 
+void TestRunner::setUserMediaPermissionForOrigin(bool permission, JSStringRef url)
+{
+    WKRetainPtr<WKStringRef> urlWK = toWK(url);
+    InjectedBundle::singleton().setUserMediaPermissionForOrigin(permission, urlWK.get());
+}
+
 bool TestRunner::callShouldCloseOnWebView()
 {
     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
index 29632f4..67c5c6c 100644 (file)
@@ -268,6 +268,7 @@ public:
 
     // MediaStream
     void setUserMediaPermission(bool);
+    void setUserMediaPermissionForOrigin(bool permission, JSStringRef url);
 
     void setPageVisibility(JSStringRef state);
     void resetPageVisibility();
index 9e6072b..8c9a57d 100644 (file)
@@ -1645,13 +1645,6 @@ bool TestController::isGeolocationProviderActive() const
     return m_geolocationProvider->isActive();
 }
 
-void TestController::setUserMediaPermission(bool enabled)
-{
-    m_isUserMediaPermissionSet = true;
-    m_isUserMediaPermissionAllowed = enabled;
-    decidePolicyForUserMediaPermissionRequestIfPossible();
-}
-
 static WKStringRef originUserVisibleName(WKSecurityOriginRef origin)
 {
     std::string host = toSTD(adoptWK(WKSecurityOriginCopyHost(origin))).c_str();
@@ -1667,6 +1660,22 @@ static WKStringRef originUserVisibleName(WKSecurityOriginRef origin)
     return WKStringCreateWithUTF8CString(userVisibleName.utf8().data());
 }
 
+void TestController::setUserMediaPermission(bool enabled)
+{
+    m_isUserMediaPermissionSet = true;
+    m_isUserMediaPermissionAllowed = enabled;
+    decidePolicyForUserMediaPermissionRequestIfPossible();
+}
+
+void TestController::setUserMediaPermissionForOrigin(bool permission, WKStringRef originString)
+{
+    if (!m_userMediaOriginPermissions)
+        m_userMediaOriginPermissions = adoptWK(WKMutableDictionaryCreate());
+    WKRetainPtr<WKBooleanRef> allowed = adoptWK(WKBooleanCreate(permission));
+    WKRetainPtr<WKSecurityOriginRef> origin = adoptWK(WKSecurityOriginCreateFromString(originString));
+    WKDictionarySetItem(m_userMediaOriginPermissions.get(), originUserVisibleName(origin.get()), allowed.get());
+}
+
 void TestController::handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef origin, const WKUserMediaPermissionCheckRef& checkRequest)
 {
     bool allowed = false;
@@ -1674,7 +1683,7 @@ void TestController::handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginR
     if (m_userMediaOriginPermissions) {
         WKRetainPtr<WKStringRef> originString = originUserVisibleName(origin);
         WKBooleanRef value = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(m_userMediaOriginPermissions.get(), originString.get()));
-        if (WKGetTypeID(value) == WKBooleanGetTypeID())
+        if (value && WKGetTypeID(value) == WKBooleanGetTypeID())
             allowed = WKBooleanGetValue(value);
     }
 
@@ -1693,17 +1702,10 @@ void TestController::decidePolicyForUserMediaPermissionRequestIfPossible()
         return;
 
     for (auto& pair : m_userMediaPermissionRequests) {
-        auto origin = pair.first.get();
         auto request = pair.second.get();
         WKRetainPtr<WKArrayRef> audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(request);
         WKRetainPtr<WKArrayRef> videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(request);
 
-        WKRetainPtr<WKStringRef> originString = adoptWK(originUserVisibleName(origin));
-        if (!m_userMediaOriginPermissions)
-            m_userMediaOriginPermissions = adoptWK(WKMutableDictionaryCreate());
-        WKRetainPtr<WKBooleanRef> allowed = adoptWK(WKBooleanCreate(m_isUserMediaPermissionAllowed));
-        WKDictionarySetItem(m_userMediaOriginPermissions.get(), originString.get(), allowed.get());
-
         if (m_isUserMediaPermissionAllowed && (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get()))) {
             WKRetainPtr<WKStringRef> videoDeviceUID;
             if (WKArrayGetSize(videoDeviceUIDs.get()))
index 841d921..ff06cfb 100644 (file)
@@ -96,6 +96,7 @@ public:
 
     // MediaStream.
     void setUserMediaPermission(bool);
+    void setUserMediaPermissionForOrigin(bool permission, WKStringRef url);
     void handleUserMediaPermissionRequest(WKSecurityOriginRef, WKUserMediaPermissionRequestRef);
     void handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef, const WKUserMediaPermissionCheckRef&);
 
index 2e0f774..b39b45c 100644 (file)
@@ -467,6 +467,21 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
         return;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermissionForOrigin")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+
+        WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission"));
+        WKBooleanRef permissionWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissionKeyWK.get()));
+        bool permission = WKBooleanGetValue(permissionWK);
+
+        WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
+        WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, urlKey.get()));
+
+        TestController::singleton().setUserMediaPermissionForOrigin(permission, urlWK);
+        return;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) {
         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
         uint64_t model = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));