Media Session: MediaSession constructor 'kind' argument optional
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Aug 2015 17:33:48 +0000 (17:33 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Aug 2015 17:33:48 +0000 (17:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148527

Reviewed by Jer Noble.

Source/WebCore:

No new tests, updated media/session/session-creation.html.

* Modules/mediasession/MediaSession.cpp:
(WebCore::MediaSession::parseKind): Treat null kind "content".
(WebCore::MediaSession::MediaSession): Delete Document* version.
* Modules/mediasession/MediaSession.h: Make constructor private.
* Modules/mediasession/MediaSession.idl:

* WebCore.xcodeproj/project.pbxproj: Add JSMediaSessionCustom.cpp.

* bindings/js/JSMediaSessionCustom.cpp: Added.
(WebCore::constructJSMediaSession):

* dom/Document.cpp:
(WebCore::Document::defaultMediaSession): Call MediaSession::create.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::session): Compare session with document.defaultMediaSession, not
  its kind.
(WebCore::HTMLMediaElement::setSession): Update comments.

LayoutTests:

* media/session/content-interruptions.html: Restructure to make less timing dependent. Minor cleanup.
* media/session/session-creation-expected.txt:
* media/session/session-creation.html: Test default MediaSession constructor argument.

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/media/session/content-interruptions.html
LayoutTests/media/session/session-creation-expected.txt
LayoutTests/media/session/session-creation.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasession/MediaSession.cpp
Source/WebCore/Modules/mediasession/MediaSession.h
Source/WebCore/Modules/mediasession/MediaSession.idl
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSMediaSessionCustom.cpp [new file with mode: 0644]
Source/WebCore/dom/Document.cpp
Source/WebCore/html/HTMLMediaElement.cpp

index 4428190..ec9fec9 100644 (file)
@@ -1,3 +1,14 @@
+2015-08-27  Eric Carlson  <eric.carlson@apple.com>
+
+        Media Session: MediaSession constructor 'kind' argument optional
+        https://bugs.webkit.org/show_bug.cgi?id=148527
+
+        Reviewed by Jer Noble.
+
+        * media/session/content-interruptions.html: Restructure to make less timing dependent. Minor cleanup.
+        * media/session/session-creation-expected.txt:
+        * media/session/session-creation.html: Test default MediaSession constructor argument.
+
 2015-08-27  Alexey Proskuryakov  <ap@apple.com>
 
         Add an expectation for another momentum scrolling test that became flaky.
index 61870f8..cd9a77d 100644 (file)
@@ -8,27 +8,25 @@
     
         function runTest() 
         {
-            if (window.testRunner) {
-                testRunner.dumpAsText();
-                testRunner.waitUntilDone();
-            }
-
-            window.jsTestIsAsync = true;
-
+            findMediaElement();
             session = new MediaSession("content");
 
             consoleWrite("Waiting for Content media to begin playing.")
-            var video = document.getElementById("video");
             video.src = findMediaFile("video", "../content/counting");
             video.session = session;
             video.onplaying = beganPlaying;
+            video.oncanplaythrough = canplaythrough;
+        }
+
+        function canplaythrough() 
+        {
             video.play();
         }
 
         function beganPlaying(event)
         {
             consoleWrite("Media began playing.");
-            document.getElementById("video").onpause = paused;
+            video.onpause = paused;
 
             if (window.internals) {
                 testExpected('internals.mediaSessionCurrentState(session)', "active");
@@ -51,6 +49,6 @@
 </head>
 <body onload="runTest()">
     <p>'Content' start of interruption events should indefinitely pause 'Content' media sessions.</p>
-    <video id="video" />
+    <video id="video" controls> </video>
 </body>
 </html>
index 9074a1c..7384386 100644 (file)
@@ -1,20 +1,30 @@
 New media sessions should be in an Idle state after creation.
 
+
 ---
-Testing 'content' session
+Testing "new MediaSession('content')"
+EXPECTED (internals.mediaSessionCurrentState(session) == 'idle') OK
 ---
+
+---
+Testing "new MediaSession('transient')"
 EXPECTED (internals.mediaSessionCurrentState(session) == 'idle') OK
 ---
-Testing 'transient' session
+
 ---
+Testing "new MediaSession('transient-solo')"
 EXPECTED (internals.mediaSessionCurrentState(session) == 'idle') OK
 ---
-Testing 'transient-solo' session
+
 ---
+Testing "new MediaSession('ambient')"
 EXPECTED (internals.mediaSessionCurrentState(session) == 'idle') OK
 ---
-Testing 'ambient' session
+
 ---
+Testing "new MediaSession()"
 EXPECTED (internals.mediaSessionCurrentState(session) == 'idle') OK
+---
+
 END OF TEST
 
index 1a54aba..d8c3d19 100644 (file)
@@ -9,20 +9,27 @@
             testSessionKind("transient");
             testSessionKind("transient-solo");
             testSessionKind("ambient");
+            testSessionKind();
 
+            consoleWrite("");
             endTest();
         }
 
         function testSessionKind(sessionKind)
         {
-            consoleWrite("---");
-            consoleWrite("Testing '" + sessionKind + "' session");
-            consoleWrite("---");
+            consoleWrite("<br>---");
 
-            session = new MediaSession(sessionKind);
+            if (sessionKind != undefined) {
+                consoleWrite("Testing \"new MediaSession('" + sessionKind + "')\"");
+                session = new MediaSession(sessionKind);
+            } else {
+                consoleWrite("Testing \"new MediaSession()\"");
+                session = new MediaSession();
+            }
 
             if (window.internals)
                 testExpected('internals.mediaSessionCurrentState(session)', "idle");
+            consoleWrite("---");
         }
     </script>
 </head>
index 76d7981..a54027e 100644 (file)
@@ -1,3 +1,31 @@
+2015-08-27  Eric Carlson  <eric.carlson@apple.com>
+
+        Media Session: MediaSession constructor 'kind' argument optional
+        https://bugs.webkit.org/show_bug.cgi?id=148527
+
+        Reviewed by Jer Noble.
+
+        No new tests, updated media/session/session-creation.html.
+
+        * Modules/mediasession/MediaSession.cpp:
+        (WebCore::MediaSession::parseKind): Treat null kind "content".
+        (WebCore::MediaSession::MediaSession): Delete Document* version.
+        * Modules/mediasession/MediaSession.h: Make constructor private.
+        * Modules/mediasession/MediaSession.idl:
+
+        * WebCore.xcodeproj/project.pbxproj: Add JSMediaSessionCustom.cpp.
+
+        * bindings/js/JSMediaSessionCustom.cpp: Added.
+        (WebCore::constructJSMediaSession):
+
+        * dom/Document.cpp:
+        (WebCore::Document::defaultMediaSession): Call MediaSession::create.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::session): Compare session with document.defaultMediaSession, not
+          its kind.
+        (WebCore::HTMLMediaElement::setSession): Update comments.
+
 2015-08-27  Zalan Bujtas  <zalan@apple.com>
 
         Simple line layout: Use float types wherever possible to match line tree.
index dd7de72..26c60c8 100644 (file)
@@ -46,21 +46,19 @@ static const char* contentKind = "content";
 MediaSession::Kind MediaSession::parseKind(const String& kind)
 {
     // 4. Media Session
-    // 2. If no corresponding media session type can be found for the provided media session category or media session
-    //    category is empty, then set media session's current media session type to "content".
+    // 2. Set media session's current media session type to the corresponding media session type of media session category.
+
+    if (kind.isNull() || kind == contentKind)
+        return MediaSession::Kind::Content;
     if (kind == ambientKind)
         return MediaSession::Kind::Ambient;
     if (kind == transientKind)
         return MediaSession::Kind::Transient;
     if (kind == transientSoloKind)
         return MediaSession::Kind::TransientSolo;
-    return MediaSession::Kind::Content;
-}
 
-MediaSession::MediaSession(Document& document)
-    : m_document(document)
-{
-    MediaSessionManager::singleton().addMediaSession(*this);
+    ASSERT_NOT_REACHED();
+    return MediaSession::Kind::Content;
 }
 
 MediaSession::MediaSession(ScriptExecutionContext& context, const String& kind)
index be6f153..df44e50 100644 (file)
@@ -53,13 +53,11 @@ public:
         Ambient
     };
 
-    static Ref<MediaSession> create(ScriptExecutionContext& context, const String& kind)
+    static Ref<MediaSession> create(ScriptExecutionContext& context, const String& kind = String())
     {
         return adoptRef(*new MediaSession(context, kind));
     }
 
-    explicit MediaSession(Document&);
-    MediaSession(ScriptExecutionContext&, const String&);
     ~MediaSession();
 
     String kind() const;
@@ -91,6 +89,8 @@ public:
 private:
     friend class HTMLMediaElement;
 
+    MediaSession(ScriptExecutionContext&, const String&);
+
     static Kind parseKind(const String&);
 
     void addMediaElement(HTMLMediaElement&);
index 3b881e0..4d42d56 100644 (file)
@@ -25,7 +25,7 @@
 
 [
     Conditional=MEDIA_SESSION,
-    Constructor(MediaSessionKind kind),
+    CustomConstructor(optional MediaSessionKind kind),
     ConstructorCallWith=ScriptExecutionContext,
     ImplementationLacksVTable,
 ] interface MediaSession {
index 1aa426d..6a64c94 100644 (file)
                077AF14018F4AE400001ED61 /* SerializedPlatformRepresentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 077AF13E18F4AE400001ED61 /* SerializedPlatformRepresentation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                077AF14318F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */; };
                077AF14418F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */; };
+               077B640F1B8F5D6B003E9AD5 /* JSMediaSessionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 077B640E1B8F5375003E9AD5 /* JSMediaSessionCustom.cpp */; };
                0783228418013ED800999E0C /* MediaStreamAudioSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0783228218013ED700999E0C /* MediaStreamAudioSource.cpp */; };
                0783228518013ED800999E0C /* MediaStreamAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0783228318013ED800999E0C /* MediaStreamAudioSource.h */; };
                07846342145B151A00A58DF1 /* JSTrackEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07846340145B151A00A58DF1 /* JSTrackEvent.cpp */; };
                077AF13E18F4AE400001ED61 /* SerializedPlatformRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SerializedPlatformRepresentation.h; sourceTree = "<group>"; };
                077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SerializedPlatformRepresentationMac.h; sourceTree = "<group>"; };
                077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SerializedPlatformRepresentationMac.mm; sourceTree = "<group>"; };
+               077B640E1B8F5375003E9AD5 /* JSMediaSessionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaSessionCustom.cpp; sourceTree = "<group>"; };
                0783228218013ED700999E0C /* MediaStreamAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamAudioSource.cpp; sourceTree = "<group>"; };
                0783228318013ED800999E0C /* MediaStreamAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamAudioSource.h; sourceTree = "<group>"; };
                07846340145B151A00A58DF1 /* JSTrackEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTrackEvent.cpp; sourceTree = "<group>"; };
                BC4EDEF70C08F414007EDD49 /* Custom */ = {
                        isa = PBXGroup;
                        children = (
+                               077B640E1B8F5375003E9AD5 /* JSMediaSessionCustom.cpp */,
                                BC2ED6BB0C6BD2F000920BFF /* JSAttrCustom.cpp */,
                                FDEAAAEF12B02EE400DCF33B /* JSAudioBufferSourceNodeCustom.cpp */,
                                FDEAAAF012B02EE400DCF33B /* JSAudioContextCustom.cpp */,
                                14DCF3B21B6BE2080062D4C2 /* JSCountQueuingStrategy.cpp in Sources */,
                                CD37B39815C1B971006DC898 /* DiagnosticLoggingKeys.cpp in Sources */,
                                CECADFC6153778FF00E37068 /* DictationAlternative.cpp in Sources */,
+                               077B640F1B8F5D6B003E9AD5 /* JSMediaSessionCustom.cpp in Sources */,
                                CECADFC8153778FF00E37068 /* DictationCommand.cpp in Sources */,
                                D0BD4F5C1408850F006839B6 /* DictationCommandIOS.cpp in Sources */,
                                312D67B11535691F00563D0D /* Dictionary.cpp in Sources */,
diff --git a/Source/WebCore/bindings/js/JSMediaSessionCustom.cpp b/Source/WebCore/bindings/js/JSMediaSessionCustom.cpp
new file mode 100644 (file)
index 0000000..697dcdd
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSMediaSession.h"
+
+#if ENABLE(MEDIA_SESSION)
+
+#include "ExceptionCode.h"
+#include "JSDOMBinding.h"
+#include "MediaSession.h"
+#include <runtime/Error.h>
+#include <runtime/JSString.h>
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+EncodedJSValue JSC_HOST_CALL constructJSMediaSession(ExecState* exec)
+{
+    auto* castedThis = jsCast<DOMConstructorObject*>(exec->callee());
+    auto* context = castedThis->scriptExecutionContext();
+    if (!context)
+        return throwConstructorDocumentUnavailableError(*exec, "MediaSession");
+
+    String kind;
+    if (exec->argumentCount() > 0) {
+        JSString* kindString = exec->argument(0).toString(exec);
+        if (UNLIKELY(exec->hadException()))
+            return JSValue::encode(jsUndefined());
+        kind = kindString->value(exec);
+        if (kind != "content" && kind != "transient" && kind != "transient-solo" && kind != "ambient")
+            return throwArgumentMustBeEnumError(*exec, 0, "kind", "MediaSession", nullptr, "\"content\", \"transient\", \"transient-solo\", \"ambient\"");
+    } else
+        kind = "content";
+
+    RefPtr<MediaSession> object = MediaSession::create(*context, kind);
+    return JSValue::encode(asObject(toJS(exec, castedThis->globalObject(), object.get())));
+}
+
+} // namespace WebCore
+
+#endif
index ffd4986..44214a9 100644 (file)
@@ -6701,7 +6701,7 @@ void Document::setShouldPlayToPlaybackTarget(uint64_t clientId, bool shouldPlay)
 MediaSession& Document::defaultMediaSession()
 {
     if (!m_defaultMediaSession)
-        m_defaultMediaSession = adoptRef(*new MediaSession(*this));
+        m_defaultMediaSession = MediaSession::create(*scriptExecutionContext());
 
     return *m_defaultMediaSession;
 }
index bb2b90a..e5d9ee5 100644 (file)
@@ -6542,36 +6542,32 @@ double HTMLMediaElement::playerVolume() const
 MediaSession* HTMLMediaElement::session() const
 {
     MediaSession* session = m_session.get();
-    if (session && session->kindEnum() == MediaSession::Kind::Default)
+    if (session && session == &document().defaultMediaSession())
         return nullptr;
+
     return session;
 }
 
 void HTMLMediaElement::setSession(MediaSession* session)
 {
-    // 6.1
+    // 6.1. Extensions to the HTMLMediaElement interface
     // 1. Let m be the media element in question.
-    // 2. Let old media session be m's current media session, if it has one, and null otherwise.
-    // 3. Let new media session be null.
-    // 4. Set m's current media session to null, if it currently has one.
-    // 5. Let m's current media session be the new value or the top-level browsing context's media session if the new
-    //    value is null.
-    // 6. If the new value is null, then set the m's kind IDL attribute to the empty string. Otherwise, set m's kind IDL
-    //    attribute to the value of current media session's kind attribute.
-    // 7. Let new media session be m's current media session.
-    // 8. Update media sessions: If old media session and new media session are the same (whether both null or both the
-    //    same media session), then terminate these steps.
-    // 9. If m is an active audio-producing participant of old media session, then pause m and remove m from old media
-    //    session's active audio-producing participants.
-    // 10. If old media session is not null and no longer has one or more active audio-producing participants, then run
-    //     the media session release algorithm for old media session.
+    // 2. Let old media session be m’s current media session, if it has one, and null otherwise.
+    // 3. Let m’s current media session be the new value or the top-level browsing context’s media session if the new value is null.
+    // 4. Let new media session be m’s current media session.
+
+    // 5. Update media sessions: If old media session and new media session are the same (whether both null or both the same media session), then terminate these steps.
+    if (m_session.get() == session)
+        return;
 
     if (m_session) {
+        // 6. If m is an audio-producing participant of old media session, then pause m and remove m from old media session’s list of audio-producing participants.
         if (m_session->isMediaElementActive(*this))
             pause();
 
         m_session->removeMediaElement(*this);
 
+        // 7. If old media session is not null and no longer has one or more audio-producing participants, then run the media session deactivation algorithm for old media session.
         if (!m_session->hasActiveMediaElements())
             m_session->releaseSession();
     }