MediaDevices.getUserMedia should put promises in resolve/reject state synchronously
https://bugs.webkit.org/show_bug.cgi?id=145308

Reviewed by Darin Adler.

Removed the calls to callToMainThread in which were resolved and rejected promises.
Cleaned up the code to remove unneeded callback copies.

Covered by existing tests.

* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::create):
(WebCore::UserMediaRequest::UserMediaRequest):
(WebCore::UserMediaRequest::didCreateStream):
(WebCore::UserMediaRequest::failedToCreateStreamWithConstraintsError):
(WebCore::UserMediaRequest::failedToCreateStreamWithPermissionError):
* Modules/mediastream/UserMediaRequest.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@185191 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index f26a17d..8fd43ed 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,23 @@
+2015-06-03  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        MediaDevices.getUserMedia should put promises in resolve/reject state synchronously
+        https://bugs.webkit.org/show_bug.cgi?id=145308
+
+        Reviewed by Darin Adler.
+
+        Removed the calls to callToMainThread in which were resolved and rejected promises.
+        Cleaned up the code to remove unneeded callback copies.
+
+        Covered by existing tests.
+
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::create):
+        (WebCore::UserMediaRequest::UserMediaRequest):
+        (WebCore::UserMediaRequest::didCreateStream):
+        (WebCore::UserMediaRequest::failedToCreateStreamWithConstraintsError):
+        (WebCore::UserMediaRequest::failedToCreateStreamWithPermissionError):
+        * Modules/mediastream/UserMediaRequest.h:
+
 2015-06-03  Simon Fraser  <simon.fraser@apple.com>
 
         REGRESSION (r184968): missing media player buttons (control bar exists, but no buttons)
diff --git a/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp b/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
index 7d6064c..cbce810 100644
--- a/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
+++ b/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
@@ -75,18 +75,29 @@
 {
     ASSERT(successCallback);
 
-    auto resolveCallback = [successCallback](MediaStream& stream) mutable {
-        successCallback->handleEvent(&stream);
+    auto resolveCallback = [successCallback, context](MediaStream& stream) mutable {
+        ASSERT(context);
+
+        RefPtr<MediaStream> mediaStream = &stream;
+        context->postTask([successCallback, mediaStream](ScriptExecutionContext&) {
+            successCallback->handleEvent(mediaStream.get());
+        });
     };
-    auto rejectCallback = [errorCallback](NavigatorUserMediaError& error) mutable {
-        if (errorCallback)
-            errorCallback->handleEvent(&error);
+    auto rejectCallback = [errorCallback, context](NavigatorUserMediaError& error) mutable {
+        ASSERT(context);
+
+        if (errorCallback) {
+            RefPtr<NavigatorUserMediaError> eventError = &error;
+            context->postTask([errorCallback, eventError](ScriptExecutionContext&) {
+                errorCallback->handleEvent(eventError.get());
+            });
+        }
     };
 
     return UserMediaRequest::create(context, controller, options, WTF::move(resolveCallback), WTF::move(rejectCallback), ec);
 }
 
-RefPtr<UserMediaRequest> UserMediaRequest::create(ScriptExecutionContext* context, UserMediaController* controller, const Dictionary& options, MediaDevices::ResolveCallback resolveCallback, MediaDevices::RejectCallback rejectCallback, ExceptionCode& ec)
+RefPtr<UserMediaRequest> UserMediaRequest::create(ScriptExecutionContext* context, UserMediaController* controller, const Dictionary& options, MediaDevices::ResolveCallback&& resolveCallback, MediaDevices::RejectCallback&& rejectCallback, ExceptionCode& ec)
 {
     ASSERT(resolveCallback && rejectCallback);
 
@@ -104,13 +115,13 @@
     return adoptRef(*new UserMediaRequest(context, controller, audioConstraints.release(), videoConstraints.release(), WTF::move(resolveCallback), WTF::move(rejectCallback)));
 }
 
-UserMediaRequest::UserMediaRequest(ScriptExecutionContext* context, UserMediaController* controller, PassRefPtr<MediaConstraints> audioConstraints, PassRefPtr<MediaConstraints> videoConstraints, MediaDevices::ResolveCallback resolveCallback, MediaDevices::RejectCallback rejectCallback)
+UserMediaRequest::UserMediaRequest(ScriptExecutionContext* context, UserMediaController* controller, PassRefPtr<MediaConstraints> audioConstraints, PassRefPtr<MediaConstraints> videoConstraints, MediaDevices::ResolveCallback&& resolveCallback, MediaDevices::RejectCallback&& rejectCallback)
     : ContextDestructionObserver(context)
     , m_audioConstraints(audioConstraints)
     , m_videoConstraints(videoConstraints)
     , m_controller(controller)
-    , m_resolveCallback(resolveCallback)
-    , m_rejectCallback(rejectCallback)
+    , m_resolveCallback(WTF::move(resolveCallback))
+    , m_rejectCallback(WTF::move(rejectCallback))
 {
 }
 
@@ -168,17 +179,14 @@
     if (!m_scriptExecutionContext)
         return;
 
-    RefPtr<UserMediaRequest> protectedThis(this);
-    callOnMainThread([protectedThis, privateStream] {
-        // 4 - Create the MediaStream and pass it to the success callback.
-        RefPtr<MediaStream> stream = MediaStream::create(*protectedThis->m_scriptExecutionContext, privateStream);
-        for (auto& track : stream->getAudioTracks())
-            track->applyConstraints(protectedThis->m_audioConstraints);
-        for (auto& track : stream->getVideoTracks())
-            track->applyConstraints(protectedThis->m_videoConstraints);
+    // 4 - Create the MediaStream and pass it to the success callback.
+    RefPtr<MediaStream> stream = MediaStream::create(*m_scriptExecutionContext, privateStream);
+    for (auto& track : stream->getAudioTracks())
+        track->applyConstraints(m_audioConstraints);
+    for (auto& track : stream->getVideoTracks())
+        track->applyConstraints(m_videoConstraints);
 
-        protectedThis->m_resolveCallback(*stream);
-    });
+    m_resolveCallback(*stream);
 }
 
 void UserMediaRequest::failedToCreateStreamWithConstraintsError(const String& constraintName)
@@ -187,11 +195,7 @@
     if (!m_scriptExecutionContext)
         return;
 
-    RefPtr<UserMediaRequest> protectedThis(this);
-    RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::constraintNotSatisfiedErrorName(), constraintName);
-    callOnMainThread([protectedThis, error] {
-        protectedThis->m_rejectCallback(*error);
-    });
+    m_rejectCallback(NavigatorUserMediaError::create(NavigatorUserMediaError::constraintNotSatisfiedErrorName(), constraintName).get());
 }
 
 void UserMediaRequest::failedToCreateStreamWithPermissionError()
@@ -199,12 +203,8 @@
     if (!m_scriptExecutionContext)
         return;
 
-    RefPtr<UserMediaRequest> protectedThis(this);
     // FIXME: Replace NavigatorUserMediaError with MediaStreamError (see bug 143335)
-    RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::permissionDeniedErrorName(), emptyString());
-    callOnMainThread([protectedThis, error] {
-        protectedThis->m_rejectCallback(*error);
-    });
+    m_rejectCallback(NavigatorUserMediaError::create(NavigatorUserMediaError::permissionDeniedErrorName(), emptyString()));
 }
 
 void UserMediaRequest::contextDestroyed()
diff --git a/Source/WebCore/Modules/mediastream/UserMediaRequest.h b/Source/WebCore/Modules/mediastream/UserMediaRequest.h
index e359a91..f3539db 100644
--- a/Source/WebCore/Modules/mediastream/UserMediaRequest.h
+++ b/Source/WebCore/Modules/mediastream/UserMediaRequest.h
@@ -59,7 +59,7 @@
 class UserMediaRequest : public MediaStreamCreationClient, public ContextDestructionObserver {
 public:
     static RefPtr<UserMediaRequest> create(ScriptExecutionContext*, UserMediaController*, const Dictionary& options, PassRefPtr<NavigatorUserMediaSuccessCallback>, PassRefPtr<NavigatorUserMediaErrorCallback>, ExceptionCode&);
-    static RefPtr<UserMediaRequest> create(ScriptExecutionContext*, UserMediaController*, const Dictionary& options, MediaDevices::ResolveCallback, MediaDevices::RejectCallback, ExceptionCode&);
+    static RefPtr<UserMediaRequest> create(ScriptExecutionContext*, UserMediaController*, const Dictionary& options, MediaDevices::ResolveCallback&&, MediaDevices::RejectCallback&&, ExceptionCode&);
     ~UserMediaRequest();
 
     WEBCORE_EXPORT SecurityOrigin* securityOrigin() const;
@@ -72,7 +72,7 @@
     bool requiresVideo() const { return m_videoConstraints; }
 
 private:
-    UserMediaRequest(ScriptExecutionContext*, UserMediaController*, PassRefPtr<MediaConstraints> audioConstraints, PassRefPtr<MediaConstraints> videoConstraints, MediaDevices::ResolveCallback, MediaDevices::RejectCallback);
+    UserMediaRequest(ScriptExecutionContext*, UserMediaController*, PassRefPtr<MediaConstraints> audioConstraints, PassRefPtr<MediaConstraints> videoConstraints, MediaDevices::ResolveCallback&&, MediaDevices::RejectCallback&&);
 
     // MediaStreamCreationClient
     virtual void constraintsValidated() override final;