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