Home | History | Annotate | Download | only in mediastream
      1 /*
      2  * Copyright (C) 2011 Ericsson AB. All rights reserved.
      3  * Copyright (C) 2012 Google Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer
     13  *    in the documentation and/or other materials provided with the
     14  *    distribution.
     15  * 3. Neither the name of Ericsson nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this
     17  *    software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "config.h"
     33 
     34 #include "modules/mediastream/UserMediaRequest.h"
     35 
     36 #include "bindings/v8/Dictionary.h"
     37 #include "bindings/v8/ExceptionState.h"
     38 #include "core/dom/Document.h"
     39 #include "core/dom/SpaceSplitString.h"
     40 #include "core/platform/mediastream/MediaStreamCenter.h"
     41 #include "core/platform/mediastream/MediaStreamDescriptor.h"
     42 #include "modules/mediastream/MediaConstraintsImpl.h"
     43 #include "modules/mediastream/MediaStream.h"
     44 #include "modules/mediastream/UserMediaController.h"
     45 
     46 namespace WebCore {
     47 
     48 static PassRefPtr<MediaConstraintsImpl> parseOptions(const Dictionary& options, const String& mediaType, ExceptionState& es)
     49 {
     50     RefPtr<MediaConstraintsImpl> constraints;
     51 
     52     Dictionary constraintsDictionary;
     53     bool ok = options.get(mediaType, constraintsDictionary);
     54     if (ok && !constraintsDictionary.isUndefinedOrNull())
     55         constraints = MediaConstraintsImpl::create(constraintsDictionary, es);
     56     else {
     57         bool mediaRequested = false;
     58         options.get(mediaType, mediaRequested);
     59         if (mediaRequested)
     60             constraints = MediaConstraintsImpl::create();
     61     }
     62 
     63     return constraints.release();
     64 }
     65 
     66 PassRefPtr<UserMediaRequest> UserMediaRequest::create(ScriptExecutionContext* context, UserMediaController* controller, const Dictionary& options, PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback, PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionState& es)
     67 {
     68     RefPtr<MediaConstraintsImpl> audio = parseOptions(options, "audio", es);
     69     if (es.hadException())
     70         return 0;
     71 
     72     RefPtr<MediaConstraintsImpl> video = parseOptions(options, "video", es);
     73     if (es.hadException())
     74         return 0;
     75 
     76     if (!audio && !video)
     77         return 0;
     78 
     79     return adoptRef(new UserMediaRequest(context, controller, audio.release(), video.release(), successCallback, errorCallback));
     80 }
     81 
     82 UserMediaRequest::UserMediaRequest(ScriptExecutionContext* context, UserMediaController* controller, PassRefPtr<MediaConstraintsImpl> audio, PassRefPtr<MediaConstraintsImpl> video, PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback, PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback)
     83     : ContextLifecycleObserver(context)
     84     , m_audio(audio)
     85     , m_video(video)
     86     , m_controller(controller)
     87     , m_successCallback(successCallback)
     88     , m_errorCallback(errorCallback)
     89 {
     90 }
     91 
     92 UserMediaRequest::~UserMediaRequest()
     93 {
     94 }
     95 
     96 bool UserMediaRequest::audio() const
     97 {
     98     return m_audio;
     99 }
    100 
    101 bool UserMediaRequest::video() const
    102 {
    103     return m_video;
    104 }
    105 
    106 MediaConstraints* UserMediaRequest::audioConstraints() const
    107 {
    108     return m_audio.get();
    109 }
    110 
    111 MediaConstraints* UserMediaRequest::videoConstraints() const
    112 {
    113     return m_video.get();
    114 }
    115 
    116 Document* UserMediaRequest::ownerDocument()
    117 {
    118     if (ScriptExecutionContext* context = scriptExecutionContext()) {
    119         return toDocument(context);
    120     }
    121 
    122     return 0;
    123 }
    124 
    125 void UserMediaRequest::start()
    126 {
    127     if (m_controller)
    128         m_controller->requestUserMedia(this);
    129 }
    130 
    131 void UserMediaRequest::succeed(PassRefPtr<MediaStreamDescriptor> streamDescriptor)
    132 {
    133     if (!scriptExecutionContext())
    134         return;
    135 
    136     RefPtr<MediaStream> stream = MediaStream::create(scriptExecutionContext(), streamDescriptor);
    137 
    138     MediaStreamTrackVector audioTracks = stream->getAudioTracks();
    139     for (MediaStreamTrackVector::iterator iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) {
    140         (*iter)->component()->source()->setConstraints(m_audio);
    141     }
    142 
    143     MediaStreamTrackVector videoTracks = stream->getVideoTracks();
    144     for (MediaStreamTrackVector::iterator iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) {
    145         (*iter)->component()->source()->setConstraints(m_video);
    146     }
    147 
    148     m_successCallback->handleEvent(stream.get());
    149 }
    150 
    151 void UserMediaRequest::fail(const String& description)
    152 {
    153     if (!scriptExecutionContext())
    154         return;
    155 
    156     if (m_errorCallback) {
    157         RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create("PERMISSION_DENIED", description, String());
    158         m_errorCallback->handleEvent(error.get());
    159     }
    160 }
    161 
    162 void UserMediaRequest::failConstraint(const String& constraintName, const String& description)
    163 {
    164     ASSERT(!constraintName.isEmpty());
    165     if (!scriptExecutionContext())
    166         return;
    167 
    168     if (m_errorCallback) {
    169         RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create("CONSTRAINT_NOT_SATISFIED", description, constraintName);
    170         m_errorCallback->handleEvent(error.get());
    171     }
    172 }
    173 
    174 void UserMediaRequest::contextDestroyed()
    175 {
    176     RefPtr<UserMediaRequest> protect(this);
    177 
    178     if (m_controller) {
    179         m_controller->cancelUserMediaRequest(this);
    180         m_controller = 0;
    181     }
    182 
    183     ContextLifecycleObserver::contextDestroyed();
    184 }
    185 
    186 } // namespace WebCore
    187