Changeset 86583 in webkit


Ignore:
Timestamp:
May 16, 2011 10:16:31 AM (13 years ago)
Author:
commit-queue@webkit.org
Message:

2011-05-16 Leandro Gracia Gil <leandrogracia@chromium.org>

Reviewed by Tony Gentilcore.

Media Stream API: add local stream requests.
https://bugs.webkit.org/show_bug.cgi?id=60177

Re-enable the argument-types test as the navigator.getUserMedia options
are now being parsed and raise the appropriate exceptions.

  • platform/chromium/test_expectations.txt:

2011-05-16 Leandro Gracia Gil <leandrogracia@chromium.org>

Reviewed by Tony Gentilcore.

Media Stream API: add local stream requests.
https://bugs.webkit.org/show_bug.cgi?id=60177

Add the code and messages for requesting the generation of local streams and getting the reply back.

Tests for the Media Stream API will be provided by the bug 56587.
One test is re-enabled with this patch.

Test: fast/dom/MediaStream/argument-types.html

  • GNUmakefile.list.am:
  • WebCore.gypi:
  • WebCore.pro:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • page/CallbackTask.h: Added. (WebCore::CallbackTask1::create): (WebCore::CallbackTask1::performTask): (WebCore::CallbackTask1::Scheduler::scheduleCallback): (WebCore::CallbackTask1::CallbackTask1):
  • page/MediaStreamClient.h:
  • page/MediaStreamController.cpp: (WebCore::MediaStreamController::isClientAvailable): (WebCore::MediaStreamController::unregisterFrameController): (WebCore::MediaStreamController::registerRequest): (WebCore::MediaStreamController::registerStream): (WebCore::MediaStreamController::generateStream): (WebCore::MediaStreamController::streamGenerated): (WebCore::MediaStreamController::streamGenerationFailed):
  • page/MediaStreamController.h:
  • page/MediaStreamFrameController.cpp: (WebCore::MediaStreamFrameController::GenerateStreamRequest::GenerateStreamRequest): (WebCore::MediaStreamFrameController::GenerateStreamRequest::~GenerateStreamRequest): (WebCore::MediaStreamFrameController::GenerateStreamRequest::isGenerateStreamRequest): (WebCore::MediaStreamFrameController::GenerateStreamRequest::abort): (WebCore::MediaStreamFrameController::GenerateStreamRequest::successCallback): (WebCore::MediaStreamFrameController::GenerateStreamRequest::errorCallback): (WebCore::::unregisterAll): (WebCore::::detachEmbedder): (WebCore::MediaStreamFrameController::MediaStreamFrameController): (WebCore::MediaStreamFrameController::pageController): (WebCore::MediaStreamFrameController::unregister): (WebCore::MediaStreamFrameController::enterDetachedState): (WebCore::MediaStreamFrameController::isClientAvailable): (WebCore::MediaStreamFrameController::disconnectFrame): (WebCore::MediaStreamFrameController::parseGenerateStreamOptions): (WebCore::MediaStreamFrameController::generateStream): (WebCore::MediaStreamFrameController::streamGenerated): (WebCore::MediaStreamFrameController::streamGenerationFailed):
  • page/MediaStreamFrameController.h: (WebCore::MediaStreamFrameController::ClientBase::ClientBase): (WebCore::MediaStreamFrameController::ClientBase::~ClientBase): (WebCore::MediaStreamFrameController::ClientBase::mediaStreamFrameController): (WebCore::MediaStreamFrameController::ClientBase::clientId): (WebCore::MediaStreamFrameController::ClientBase::isStream): (WebCore::MediaStreamFrameController::ClientBase::isGeneratedStream): (WebCore::MediaStreamFrameController::ClientBase::detachEmbedder): (WebCore::MediaStreamFrameController::ClientBase::associateFrameController): (WebCore::MediaStreamFrameController::ClientBase::unregisterClient): (WebCore::MediaStreamFrameController::StreamClient::StreamClient): (WebCore::MediaStreamFrameController::StreamClient::~StreamClient): (WebCore::MediaStreamFrameController::StreamClient::isStream): (WebCore::MediaStreamFrameController::StreamClient::unregister): (WebCore::MediaStreamFrameController::IdGenerator::IdGenerator): (WebCore::MediaStreamFrameController::IdGenerator::getNextId): (WebCore::MediaStreamFrameController::ClientMapBase::ClientMapBase):
  • page/Navigator.cpp: (WebCore::Navigator::webkitGetUserMedia):
  • page/NavigatorUserMediaErrorCallback.h:
Location:
trunk
Files:
15 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r86579 r86583  
     12011-05-16  Leandro Gracia Gil  <leandrogracia@chromium.org>
     2
     3        Reviewed by Tony Gentilcore.
     4
     5        Media Stream API: add local stream requests.
     6        https://bugs.webkit.org/show_bug.cgi?id=60177
     7
     8        Re-enable the argument-types test as the navigator.getUserMedia options
     9        are now being parsed and raise the appropriate exceptions.
     10
     11        * platform/chromium/test_expectations.txt:
     12
    1132011-05-16  Mark Pilgrim  <pilgrim@chromium.org>
    214
  • trunk/LayoutTests/platform/chromium/test_expectations.txt

    r86570 r86583  
    40264026BUGWK54181 : fast/events/page-visibility-transition-test.html = TIMEOUT
    40274027
    4028 // To be re-enabled after landing https://bugs.webkit.org/show_bug.cgi?id=60177.
    4029 BUGWK60387 : fast/dom/MediaStream/argument-types.html = FAIL
    4030 
    40314028BUGCR82281 : fast/xpath/xpath-iterator-result-should-mark-its-nodeset.html = TEXT
    40324029BUGCR82281 : fast/xpath/xpath-other-nodeset-result-should-mark-its-nodeset.html = TEXT
  • trunk/Source/WebCore/ChangeLog

    r86581 r86583  
     12011-05-16  Leandro Gracia Gil  <leandrogracia@chromium.org>
     2
     3        Reviewed by Tony Gentilcore.
     4
     5        Media Stream API: add local stream requests.
     6        https://bugs.webkit.org/show_bug.cgi?id=60177
     7
     8        Add the code and messages for requesting the generation of local streams and getting the reply back.
     9
     10        Tests for the Media Stream API will be provided by the bug 56587.
     11        One test is re-enabled with this patch.
     12
     13        Test: fast/dom/MediaStream/argument-types.html
     14
     15        * GNUmakefile.list.am:
     16        * WebCore.gypi:
     17        * WebCore.pro:
     18        * WebCore.vcproj/WebCore.vcproj:
     19        * WebCore.xcodeproj/project.pbxproj:
     20        * page/CallbackTask.h: Added.
     21        (WebCore::CallbackTask1::create):
     22        (WebCore::CallbackTask1::performTask):
     23        (WebCore::CallbackTask1::Scheduler::scheduleCallback):
     24        (WebCore::CallbackTask1::CallbackTask1):
     25        * page/MediaStreamClient.h:
     26        * page/MediaStreamController.cpp:
     27        (WebCore::MediaStreamController::isClientAvailable):
     28        (WebCore::MediaStreamController::unregisterFrameController):
     29        (WebCore::MediaStreamController::registerRequest):
     30        (WebCore::MediaStreamController::registerStream):
     31        (WebCore::MediaStreamController::generateStream):
     32        (WebCore::MediaStreamController::streamGenerated):
     33        (WebCore::MediaStreamController::streamGenerationFailed):
     34        * page/MediaStreamController.h:
     35        * page/MediaStreamFrameController.cpp:
     36        (WebCore::MediaStreamFrameController::GenerateStreamRequest::GenerateStreamRequest):
     37        (WebCore::MediaStreamFrameController::GenerateStreamRequest::~GenerateStreamRequest):
     38        (WebCore::MediaStreamFrameController::GenerateStreamRequest::isGenerateStreamRequest):
     39        (WebCore::MediaStreamFrameController::GenerateStreamRequest::abort):
     40        (WebCore::MediaStreamFrameController::GenerateStreamRequest::successCallback):
     41        (WebCore::MediaStreamFrameController::GenerateStreamRequest::errorCallback):
     42        (WebCore::::unregisterAll):
     43        (WebCore::::detachEmbedder):
     44        (WebCore::MediaStreamFrameController::MediaStreamFrameController):
     45        (WebCore::MediaStreamFrameController::pageController):
     46        (WebCore::MediaStreamFrameController::unregister):
     47        (WebCore::MediaStreamFrameController::enterDetachedState):
     48        (WebCore::MediaStreamFrameController::isClientAvailable):
     49        (WebCore::MediaStreamFrameController::disconnectFrame):
     50        (WebCore::MediaStreamFrameController::parseGenerateStreamOptions):
     51        (WebCore::MediaStreamFrameController::generateStream):
     52        (WebCore::MediaStreamFrameController::streamGenerated):
     53        (WebCore::MediaStreamFrameController::streamGenerationFailed):
     54        * page/MediaStreamFrameController.h:
     55        (WebCore::MediaStreamFrameController::ClientBase::ClientBase):
     56        (WebCore::MediaStreamFrameController::ClientBase::~ClientBase):
     57        (WebCore::MediaStreamFrameController::ClientBase::mediaStreamFrameController):
     58        (WebCore::MediaStreamFrameController::ClientBase::clientId):
     59        (WebCore::MediaStreamFrameController::ClientBase::isStream):
     60        (WebCore::MediaStreamFrameController::ClientBase::isGeneratedStream):
     61        (WebCore::MediaStreamFrameController::ClientBase::detachEmbedder):
     62        (WebCore::MediaStreamFrameController::ClientBase::associateFrameController):
     63        (WebCore::MediaStreamFrameController::ClientBase::unregisterClient):
     64        (WebCore::MediaStreamFrameController::StreamClient::StreamClient):
     65        (WebCore::MediaStreamFrameController::StreamClient::~StreamClient):
     66        (WebCore::MediaStreamFrameController::StreamClient::isStream):
     67        (WebCore::MediaStreamFrameController::StreamClient::unregister):
     68        (WebCore::MediaStreamFrameController::IdGenerator::IdGenerator):
     69        (WebCore::MediaStreamFrameController::IdGenerator::getNextId):
     70        (WebCore::MediaStreamFrameController::ClientMapBase::ClientMapBase):
     71        * page/Navigator.cpp:
     72        (WebCore::Navigator::webkitGetUserMedia):
     73        * page/NavigatorUserMediaErrorCallback.h:
     74
    1752011-05-16  Pavel Podivilov  <podivilov@chromium.org>
    276
  • trunk/Source/WebCore/GNUmakefile.list.am

    r86451 r86583  
    21362136        Source/WebCore/page/BarInfo.cpp \
    21372137        Source/WebCore/page/BarInfo.h \
     2138        Source/WebCore/page/CallbackTask.h \
    21382139        Source/WebCore/page/Chrome.cpp \
    21392140        Source/WebCore/page/Chrome.h \
  • trunk/Source/WebCore/WebCore.gypi

    r86315 r86583  
    33923392            'page/BarInfo.cpp',
    33933393            'page/BarInfo.h',
     3394            'page/CallbackTask.h',
    33943395            'page/Chrome.cpp',
    33953396            'page/Console.cpp',
  • trunk/Source/WebCore/WebCore.pro

    r86451 r86583  
    31033103contains(DEFINES, ENABLE_MEDIA_STREAM=1) {
    31043104    HEADERS += \
     3105        page/CallbackTask.h \
    31053106        page/MediaStreamClient.h \
    31063107        page/MediaStreamController.h \
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r86451 r86583  
    2440724407                        </File>
    2440824408                        <File
     24409                                RelativePath="..\page\CallbackTask.h"
     24410                                >
     24411                        </File>
     24412                        <File
    2440924413                                RelativePath="..\page\Chrome.cpp"
    2441024414                                >
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r86472 r86583  
    40924092                B1E54597134629C10092A545 /* MediaStreamController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1E5458B134629C10092A545 /* MediaStreamController.cpp */; };
    40934093                B1E54598134629C10092A545 /* MediaStreamController.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E5458C134629C10092A545 /* MediaStreamController.h */; };
     4094                B1E54593134629C10092A545 /* CallbackTask.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E54587134629C10092A545 /* CallbackTask.h */; };
    40944095                B1E54599134629C10092A545 /* NavigatorUserMediaError.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E5458D134629C10092A545 /* NavigatorUserMediaError.h */; };
    40954096                B1E5459B134629C10092A545 /* NavigatorUserMediaErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E5458F134629C10092A545 /* NavigatorUserMediaErrorCallback.h */; };
     
    1034910350                B1E5458B134629C10092A545 /* MediaStreamController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamController.cpp; sourceTree = "<group>"; };
    1035010351                B1E5458C134629C10092A545 /* MediaStreamController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamController.h; sourceTree = "<group>"; };
     10352                B1E54587134629C10092A545 /* CallbackTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallbackTask.h; sourceTree = "<group>"; };
    1035110353                B1E5458D134629C10092A545 /* NavigatorUserMediaError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorUserMediaError.h; sourceTree = "<group>"; };
    1035210354                B1E5458E134629C10092A545 /* NavigatorUserMediaError.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorUserMediaError.idl; sourceTree = "<group>"; };
     
    1409714099                                BC124EE50C2641CD009E2349 /* BarInfo.h */,
    1409814100                                BC124EE60C2641CD009E2349 /* BarInfo.idl */,
     14101                                B1E54587134629C10092A545 /* CallbackTask.h */,
    1409914102                                14D8238A0AF92DF60004F057 /* Chrome.cpp */,
    1410014103                                14D823500AF92A790004F057 /* Chrome.h */,
     
    2277422777                                BCE5644E137A34D6007D2934 /* ConsoleTypes.h in Headers */,
    2277522778                                BCF7E491137CD7C7001DDAE7 /* AdjustViewSizeOrNot.h in Headers */,
     22779                                B1E54593134629C10092A545 /* CallbackTask.h in Headers */,
    2277622780                        );
    2277722781                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/WebCore/page/CallbackTask.h

    r86582 r86583  
    2323 */
    2424
    25 #ifndef MediaStreamFrameController_h
    26 #define MediaStreamFrameController_h
     25#ifndef CallbackTask_h
     26#define CallbackTask_h
    2727
    2828#if ENABLE(MEDIA_STREAM)
    2929
     30#include "ScriptExecutionContext.h"
    3031#include <wtf/Forward.h>
    31 #include <wtf/HashMap.h>
    32 #include <wtf/Noncopyable.h>
     32#include <wtf/PassRefPtr.h>
     33#include <wtf/RefPtr.h>
    3334
    3435namespace WebCore {
    3536
    36 class Frame;
    37 class MediaStreamController;
    38 class Page;
    39 class ScriptExecutionContext;
    40 class SecurityOrigin;
     37// Helper template to schedule calls to callbacks using their own script execution context.
     38// CallbackType is assumed to implement Scheduler and to be reference-counted.
     39template <typename CallbackType, typename ArgumentType>
     40class CallbackTask1 : public ScriptExecutionContext::Task {
     41public:
     42    static PassOwnPtr<CallbackTask1> create(PassRefPtr<CallbackType> callback, PassRefPtr<ArgumentType> data)
     43    {
     44        return adoptPtr(new CallbackTask1(callback, data));
     45    }
    4146
    42 class MediaStreamFrameController {
    43     WTF_MAKE_NONCOPYABLE(MediaStreamFrameController);
    44 public:
    45     MediaStreamFrameController(Frame*);
    46     virtual ~MediaStreamFrameController();
     47    virtual void performTask(ScriptExecutionContext*)
     48    {
     49        m_callback->handleEvent(m_data.get());
     50    }
    4751
    48     SecurityOrigin* securityOrigin() const;
    49     ScriptExecutionContext* scriptExecutionContext() const;
    50 
    51     void disconnectPage();
    52     void disconnectFrame();
    53     void transferToNewPage(Page*);
     52    class Scheduler {
     53    public:
     54        bool scheduleCallback(ScriptExecutionContext* context, PassRefPtr<ArgumentType> data)
     55        {
     56            if (context) {
     57                context->postTask(CallbackTask1<CallbackType, ArgumentType>::create(static_cast<CallbackType*>(this), data));
     58                return true;
     59            }
     60            return false;
     61        }
     62    };
    5463
    5564private:
    56     class Request;
     65    CallbackTask1(PassRefPtr<CallbackType> callback, PassRefPtr<ArgumentType> data)
     66        : m_callback(callback)
     67        , m_data(data)
     68    {
     69    }
    5770
    58     class RequestMap : public HashMap<int, RefPtr<Request> > {
    59     public:
    60         void abort(int requestId);
    61         void abortAll();
    62     };
    63 
    64     // Detached from a page, and hence from a embedder client.
    65     void enterDetachedState();
    66 
    67     MediaStreamController* pageController() const;
    68 
    69     RequestMap m_requests;
    70 
    71     Frame* m_frame;
    72     bool m_isInDetachedState;
     71    RefPtr<CallbackType> m_callback;
     72    RefPtr<ArgumentType> m_data;
    7373};
    7474
    75 } // namespace WebCore
     75}
    7676
    7777#endif // ENABLE(MEDIA_STREAM)
    7878
    79 #endif // MediaStreamFrameController_h
     79#endif // CallbackTask_h
  • trunk/Source/WebCore/page/MediaStreamClient.h

    r85745 r86583  
    2828#if ENABLE(MEDIA_STREAM)
    2929
     30#include <wtf/Forward.h>
     31
    3032namespace WebCore {
     33
     34class SecurityOrigin;
     35
     36enum GenerateStreamOptionFlag {
     37    GenerateStreamRequestAudio = 1,
     38    GenerateStreamRequestVideoFacingUser = 1 << 1,
     39    GenerateStreamRequestVideoFacingEnvironment = 1 << 2,
     40};
     41
     42typedef unsigned GenerateStreamOptionFlags;
    3143
    3244class MediaStreamClient {
     
    3547    virtual void mediaStreamDestroyed() = 0;
    3648
    37     // FIXME: add here the requests to the embedder.
     49    // Generate a new local stream.
     50    virtual void generateStream(int requestId, GenerateStreamOptionFlags, PassRefPtr<SecurityOrigin>) = 0;
    3851
    3952protected:
  • trunk/Source/WebCore/page/MediaStreamController.cpp

    r85745 r86583  
    2828#if ENABLE(MEDIA_STREAM)
    2929
    30 #include "MediaStreamClient.h"
    3130#include "MediaStreamFrameController.h"
     31#include "SecurityOrigin.h"
    3232#include <wtf/Vector.h>
    3333
     
    6464}
    6565
     66bool MediaStreamController::isClientAvailable() const
     67{
     68    return m_client;
     69}
     70
    6671void MediaStreamController::unregisterFrameController(MediaStreamFrameController* frameController)
    6772{
     
    7681    for (Vector<int>::iterator it = frameRequests.begin(); it != frameRequests.end(); ++it)
    7782        m_requests.remove(*it);
     83
     84    Vector<String> frameStreams;
     85    for (StreamMap::iterator it = m_streams.begin(); it != m_streams.end(); ++it)
     86        if (it->second == frameController)
     87            frameStreams.append(it->first);
     88
     89    for (Vector<String>::iterator it = frameStreams.begin(); it != frameStreams.end(); ++it)
     90        m_streams.remove(*it);
    7891}
    7992
    8093int MediaStreamController::registerRequest(int localId, MediaStreamFrameController* frameController)
    8194{
     95    ASSERT(localId > 0);
     96    ASSERT(frameController);
    8297    m_requests.add(m_nextGlobalRequestId, Request(localId, frameController));
    8398    return m_nextGlobalRequestId++;
     99}
     100
     101void MediaStreamController::registerStream(const String& streamLabel, MediaStreamFrameController* frameController)
     102{
     103    ASSERT(frameController);
     104    ASSERT(!m_streams.contains(streamLabel));
     105    m_streams.add(streamLabel, frameController);
     106}
     107
     108void MediaStreamController::generateStream(MediaStreamFrameController* frameController, int localId, GenerateStreamOptionFlags flags, PassRefPtr<SecurityOrigin> securityOrigin)
     109{
     110    ASSERT(m_client);
     111    int controllerRequestId = registerRequest(localId, frameController);
     112    m_client->generateStream(controllerRequestId, flags, securityOrigin);
     113}
     114
     115void MediaStreamController::streamGenerated(int controllerRequestId, const String& streamLabel)
     116{
     117    // Don't assert since the frame controller can have been destroyed while the request reply was coming back.
     118    if (m_requests.contains(controllerRequestId)) {
     119        const Request& request = m_requests.get(controllerRequestId);
     120        registerStream(streamLabel, request.frameController());
     121        m_requests.remove(controllerRequestId);
     122        ASSERT(request.frameController());
     123        request.frameController()->streamGenerated(request.localId(), streamLabel);
     124    }
     125}
     126
     127void MediaStreamController::streamGenerationFailed(int controllerRequestId, NavigatorUserMediaError::ErrorCode code)
     128{
     129    // Don't assert since the frame controller can have been destroyed while the request reply was coming back.
     130    if (m_requests.contains(controllerRequestId)) {
     131        const Request& request = m_requests.get(controllerRequestId);
     132        m_requests.remove(controllerRequestId);
     133        request.frameController()->streamGenerationFailed(request.localId(), code);
     134    }
    84135}
    85136
  • trunk/Source/WebCore/page/MediaStreamController.h

    r85745 r86583  
    2828#if ENABLE(MEDIA_STREAM)
    2929
     30#include "MediaStreamClient.h"
     31#include "NavigatorUserMediaError.h"
    3032#include <wtf/Forward.h>
    3133#include <wtf/HashMap.h>
    3234#include <wtf/Noncopyable.h>
     35#include <wtf/text/StringHash.h>
    3336
    3437namespace WebCore {
     
    3639class MediaStreamClient;
    3740class MediaStreamFrameController;
     41class SecurityOrigin;
    3842
    3943class MediaStreamController {
     
    4347    virtual ~MediaStreamController();
    4448
     49    bool isClientAvailable() const;
    4550    void unregisterFrameController(MediaStreamFrameController*);
     51
     52    void generateStream(MediaStreamFrameController*, int requestId, GenerateStreamOptionFlags, PassRefPtr<SecurityOrigin>);
     53
     54    void streamGenerated(int requestId, const String& streamLabel);
     55    void streamGenerationFailed(int requestId, NavigatorUserMediaError::ErrorCode);
    4656
    4757private:
    4858    int registerRequest(int localRequestId, MediaStreamFrameController*);
     59    void registerStream(const String& streamLabel, MediaStreamFrameController*);
    4960
    5061    class Request;
    5162    typedef HashMap<int, Request> RequestMap;
     63    typedef HashMap<String, MediaStreamFrameController*> StreamMap;
    5264
    5365    RequestMap m_requests;
     66    StreamMap m_streams;
    5467
    5568    MediaStreamClient* m_client;
  • trunk/Source/WebCore/page/MediaStreamFrameController.cpp

    r85745 r86583  
    4141
    4242class MediaStreamFrameController::Request : public RefCounted<Request> {
     43    WTF_MAKE_NONCOPYABLE(Request);
    4344public:
    4445    Request(ScriptExecutionContext* scriptExecutionContext)
     
    5960};
    6061
     62class MediaStreamFrameController::GenerateStreamRequest : public Request {
     63    WTF_MAKE_NONCOPYABLE(GenerateStreamRequest);
     64public:
     65    GenerateStreamRequest(ScriptExecutionContext* scriptExecutionContext,
     66                          PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback,
     67                          PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback)
     68        : Request(scriptExecutionContext)
     69        , m_successCallback(successCallback)
     70        , m_errorCallback(errorCallback) { }
     71
     72    virtual ~GenerateStreamRequest() { }
     73
     74    virtual bool isGenerateStreamRequest() const { return true; }
     75
     76    virtual void abort()
     77    {
     78        if (m_errorCallback) {
     79            RefPtr<NavigatorUserMediaError> error = adoptRef(new NavigatorUserMediaError(NavigatorUserMediaError::PERMISSION_DENIED));
     80            // The callback itself is made with the JS callback's context, not with the frame's context.
     81            m_errorCallback->scheduleCallback(scriptExecutionContext(), error);
     82        }
     83    }
     84
     85    PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback() const { return m_successCallback; }
     86    PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback() const { return m_errorCallback; }
     87
     88private:
     89    RefPtr<NavigatorUserMediaSuccessCallback> m_successCallback;
     90    RefPtr<NavigatorUserMediaErrorCallback> m_errorCallback;
     91};
     92
    6193void MediaStreamFrameController::RequestMap::abort(int requestId)
    6294{
     
    73105}
    74106
     107template <typename T>
     108void MediaStreamFrameController::ClientMapBase<T>::unregisterAll()
     109{
     110    while (!this->isEmpty()) {
     111        T key = this->begin()->first;
     112        // unregister should remove the element from the map.
     113        this->begin()->second->unregister();
     114        ASSERT_UNUSED(key, !this->contains(key));
     115    }
     116}
     117
     118template <typename T>
     119void MediaStreamFrameController::ClientMapBase<T>::detachEmbedder()
     120{
     121    for (typename MapType::iterator it = this->begin(); it != this->end(); ++it)
     122        it->second->detachEmbedder();
     123}
     124
    75125MediaStreamFrameController::MediaStreamFrameController(Frame* frame)
    76126    : m_frame(frame)
    77127    , m_isInDetachedState(false)
    78128{
     129    if (!isClientAvailable())
     130        enterDetachedState();
    79131}
    80132
     
    95147MediaStreamController* MediaStreamFrameController::pageController() const
    96148{
    97     return !m_isInDetachedState && m_frame && m_frame->page() ? m_frame->page()->mediaStreamController() : 0;
     149    return m_frame && m_frame->page() ? m_frame->page()->mediaStreamController() : 0;
     150}
     151
     152void MediaStreamFrameController::unregister(StreamClient* client)
     153{
     154    ASSERT(m_streams.contains(client->clientId()));
     155    m_streams.remove(client->clientId());
    98156}
    99157
     
    106164
    107165    m_requests.abortAll();
     166    m_streams.detachEmbedder();
    108167    m_isInDetachedState = true;
     168}
     169
     170bool MediaStreamFrameController::isClientAvailable() const
     171{
     172    if (m_isInDetachedState)
     173        return false;
     174
     175    MediaStreamController* controller = pageController();
     176    return controller && controller->isClientAvailable();
    109177}
    110178
     
    124192
    125193    ASSERT(m_requests.isEmpty());
     194    m_streams.unregisterAll();
    126195
    127196    m_frame = 0;
     
    135204}
    136205
     206GenerateStreamOptionFlags MediaStreamFrameController::parseGenerateStreamOptions(const String& options)
     207{
     208    GenerateStreamOptionFlags flags = 0;
     209    Vector<String> optionList;
     210    options.split(',', optionList);
     211
     212    for (Vector<String>::const_iterator option = optionList.begin(); option != optionList.end(); ++option) {
     213        Vector<String> suboptionList;
     214        option->split(' ', suboptionList);
     215
     216        if (suboptionList.first() == "audio")
     217            flags |= GenerateStreamRequestAudio;
     218        else if (suboptionList.first() == "video") {
     219            bool videoSuboptions = false;
     220            Vector<String>::const_iterator suboption = suboptionList.begin();
     221            for (++suboption; suboption != suboptionList.end(); ++suboption)
     222                if (*suboption == "user") {
     223                    flags |= GenerateStreamRequestVideoFacingUser;
     224                    videoSuboptions = true;
     225                } else if (*suboption == "environment") {
     226                    flags |= GenerateStreamRequestVideoFacingEnvironment;
     227                    videoSuboptions = true;
     228                }
     229
     230            // Ask for all kind of cameras if no suboption was specified.
     231            if (!videoSuboptions)
     232                flags |= GenerateStreamRequestVideoFacingUser | GenerateStreamRequestVideoFacingEnvironment;
     233        }
     234    }
     235
     236    return flags;
     237}
     238
     239// Implements the getUserMedia method from http://www.whatwg.org/specs/web-apps/current-work/#dom-navigator-getusermedia.
     240void MediaStreamFrameController::generateStream(const String& options,
     241                                                PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback,
     242                                                PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback,
     243                                                ExceptionCode& ec)
     244{
     245    ec = 0;
     246    if (!successCallback)
     247        return;
     248
     249    GenerateStreamOptionFlags flags = parseGenerateStreamOptions(options);
     250    if (!flags) {
     251        ec = NOT_SUPPORTED_ERR;
     252        return;
     253    }
     254
     255    int requestId = m_requests.getNextId();
     256    m_requests.add(requestId, adoptRef(new GenerateStreamRequest(scriptExecutionContext(), successCallback, errorCallback)));
     257
     258    if (!isClientAvailable()) {
     259        // This makes sure to call the error callback if provided.
     260        m_requests.abort(requestId);
     261        return;
     262    }
     263
     264    pageController()->generateStream(this, requestId, flags, securityOrigin());
     265}
     266
     267void MediaStreamFrameController::streamGenerated(int requestId, const String& label)
     268{
     269    // Don't assert since the request can have been aborted as a result of embedder detachment.
     270    if (m_requests.contains(requestId)) {
     271        ASSERT(m_requests.get(requestId)->isGenerateStreamRequest());
     272        ASSERT(!label.isNull());
     273
     274        // FIXME: create a GeneratedStream object and invoke the callback when the class is available.
     275        m_requests.remove(requestId);
     276    }
     277}
     278
     279void MediaStreamFrameController::streamGenerationFailed(int requestId, NavigatorUserMediaError::ErrorCode code)
     280{
     281    // Don't assert since the request can have been aborted as a result of embedder detachment.
     282    if (m_requests.contains(requestId)) {
     283        ASSERT(m_requests.get(requestId)->isGenerateStreamRequest());
     284
     285        RefPtr<GenerateStreamRequest> streamRequest = static_cast<GenerateStreamRequest*>(m_requests.get(requestId).get());
     286        m_requests.remove(requestId);
     287
     288        if (streamRequest->errorCallback()) {
     289            RefPtr<NavigatorUserMediaError> error = adoptRef(new NavigatorUserMediaError(code));
     290            streamRequest->errorCallback()->handleEvent(error.get());
     291        }
     292    }
     293}
     294
    137295} // namespace WebCore
    138296
  • trunk/Source/WebCore/page/MediaStreamFrameController.h

    r85745 r86583  
    2828#if ENABLE(MEDIA_STREAM)
    2929
     30#include "ExceptionCode.h"
     31#include "MediaStreamClient.h"
     32#include "NavigatorUserMediaError.h"
    3033#include <wtf/Forward.h>
    3134#include <wtf/HashMap.h>
    3235#include <wtf/Noncopyable.h>
     36#include <wtf/text/StringHash.h>
    3337
    3438namespace WebCore {
     
    3640class Frame;
    3741class MediaStreamController;
     42class NavigatorUserMediaErrorCallback;
     43class NavigatorUserMediaSuccessCallback;
    3844class Page;
    3945class ScriptExecutionContext;
     
    4349    WTF_MAKE_NONCOPYABLE(MediaStreamFrameController);
    4450public:
     51    template <typename IdType>
     52    class ClientBase {
     53        WTF_MAKE_NONCOPYABLE(ClientBase);
     54    public:
     55        ClientBase() : m_frameController(0), m_clientId(0) { }
     56
     57        ClientBase(MediaStreamFrameController* frameController, const IdType& id)
     58            : m_frameController(frameController)
     59            , m_clientId(id) { }
     60
     61        virtual ~ClientBase() { }
     62
     63        MediaStreamFrameController* mediaStreamFrameController() const { return m_frameController; }
     64        const IdType& clientId() const { return m_clientId; }
     65
     66        virtual bool isStream() const { return false; }
     67        virtual bool isGeneratedStream() const { return false; }
     68
     69        // Called when the frame controller is being disconnected to the MediaStreamClient embedder.
     70        // Clients should override this to send any required shutdown messages.
     71        virtual void detachEmbedder() { }
     72
     73    protected:
     74        // Used for objects that are optionally associated to the frame controller after construction, like the track lists.
     75        void associateFrameController(MediaStreamFrameController* frameController, const IdType& id)
     76        {
     77            ASSERT(!m_frameController && !m_clientId);
     78            m_frameController = frameController;
     79            m_clientId = id;
     80        }
     81
     82        // Avoids repeating the same code in the unregister method of each derived class.
     83        // This is required since the controller's unregister methods make use of the isObject virtuals,
     84        // and the unregistration can be triggered either by the destructor of the client or by the disconnection of the frame.
     85        template <typename ClientType>
     86        void unregisterClient(ClientType* client)
     87        {
     88            if (!m_frameController)
     89                return;
     90
     91            m_frameController->unregister(static_cast<ClientType*>(client));
     92            m_frameController = 0;
     93        }
     94
     95        virtual void unregister() = 0;
     96        friend class MediaStreamFrameController;
     97
     98        MediaStreamFrameController* m_frameController;
     99        IdType m_clientId;
     100    };
     101
     102    class StreamClient : public ClientBase<String> {
     103    public:
     104        StreamClient(MediaStreamFrameController* frameController, const String& label) : ClientBase<String>(frameController, label) { }
     105        virtual ~StreamClient() { unregister(); }
     106
     107        virtual bool isStream() const { return true; }
     108
     109        // Stream has ended for some external reason.
     110        virtual void streamEnded() = 0;
     111
     112    private:
     113        virtual void unregister() { unregisterClient(this); }
     114    };
     115
    45116    MediaStreamFrameController(Frame*);
    46117    virtual ~MediaStreamFrameController();
     
    49120    ScriptExecutionContext* scriptExecutionContext() const;
    50121
     122    bool isClientAvailable() const;
    51123    void disconnectPage();
    52124    void disconnectFrame();
    53125    void transferToNewPage(Page*);
    54126
     127    // Parse the options string provided to the generateStream method.
     128    static GenerateStreamOptionFlags parseGenerateStreamOptions(const String&);
     129
     130    // Create a new generated stream asynchronously with the provided options.
     131    void generateStream(const String& options, PassRefPtr<NavigatorUserMediaSuccessCallback>, PassRefPtr<NavigatorUserMediaErrorCallback>, ExceptionCode&);
     132
     133    // --- Calls coming back from the controller. --- //
     134
     135    // Report the generation of a new local stream.
     136    void streamGenerated(int requestId, const String& streamLabel);
     137
     138    // Report a failure in the generation of a new stream.
     139    void streamGenerationFailed(int requestId, NavigatorUserMediaError::ErrorCode);
     140
    55141private:
    56142    class Request;
     143    class GenerateStreamRequest;
    57144
    58     class RequestMap : public HashMap<int, RefPtr<Request> > {
     145    class IdGenerator {
     146        WTF_MAKE_NONCOPYABLE(IdGenerator);
     147    public:
     148        IdGenerator() : m_id(0) { }
     149        int getNextId() { return ++m_id; }
     150
     151    private:
     152        int m_id;
     153    };
     154
     155    class RequestMap : public IdGenerator, public HashMap<int, RefPtr<Request> > {
    59156    public:
    60157        void abort(int requestId);
     
    62159    };
    63160
     161    template <typename IdType>
     162    class ClientMapBase : public HashMap<IdType, ClientBase<IdType>* > {
     163        WTF_MAKE_NONCOPYABLE(ClientMapBase);
     164    public:
     165        typedef HashMap<IdType, ClientBase<IdType>* > MapType;
     166
     167        ClientMapBase() { }
     168        void unregisterAll();
     169        void detachEmbedder();
     170    };
     171
     172    // Streams are a special class of clients since they are identified by a global label string instead of an id.
     173    typedef ClientMapBase<String> StreamMap;
     174
    64175    // Detached from a page, and hence from a embedder client.
    65176    void enterDetachedState();
    66177
     178    void unregister(StreamClient*);
    67179    MediaStreamController* pageController() const;
    68180
    69181    RequestMap m_requests;
     182    StreamMap m_streams;
    70183
    71184    Frame* m_frame;
  • trunk/Source/WebCore/page/Navigator.cpp

    r86055 r86583  
    3636#include "KURL.h"
    3737#include "Language.h"
     38#include "MediaStreamFrameController.h"
    3839#include "NavigatorUserMediaErrorCallback.h"
    3940#include "NavigatorUserMediaSuccessCallback.h"
     
    246247
    247248#if ENABLE(MEDIA_STREAM)
    248 void Navigator::webkitGetUserMedia(const String&, PassRefPtr<NavigatorUserMediaSuccessCallback>, PassRefPtr<NavigatorUserMediaErrorCallback>, ExceptionCode&)
    249 {
    250     // FIXME: implement a call to the media stream context when available.
     249void Navigator::webkitGetUserMedia(const String& options, PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback, PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionCode& ec)
     250{
     251    if (m_frame && m_frame->mediaStreamFrameController())
     252        m_frame->mediaStreamFrameController()->generateStream(options, successCallback, errorCallback, ec);
    251253}
    252254#endif
  • trunk/Source/WebCore/page/NavigatorUserMediaErrorCallback.h

    r83287 r86583  
    2828#if ENABLE(MEDIA_STREAM)
    2929
     30#include "CallbackTask.h"
     31#include "NavigatorUserMediaError.h"
    3032#include <wtf/RefCounted.h>
    3133
    3234namespace WebCore {
    3335
    34 class NavigatorUserMediaError;
    35 
    36 class NavigatorUserMediaErrorCallback : public RefCounted<NavigatorUserMediaErrorCallback> {
     36class NavigatorUserMediaErrorCallback : public RefCounted<NavigatorUserMediaErrorCallback>,
     37                                        public CallbackTask1<NavigatorUserMediaErrorCallback, NavigatorUserMediaError>::Scheduler {
    3738public:
    3839    virtual ~NavigatorUserMediaErrorCallback() { }
Note: See TracChangeset for help on using the changeset viewer.