Title: [209227] trunk
Revision
209227
Author
grao...@webkit.org
Date
2016-12-01 18:07:35 -0800 (Thu, 01 Dec 2016)

Log Message

[Modern Media Controls] Show and populate the tracks panel
https://bugs.webkit.org/show_bug.cgi?id=165284

Reviewed by Dean Jackson.

We added a TracksPanel in https://bugs.webkit.org/show_bug.cgi?id=165239 which allows to
show a list of media tracks and text tracks to choose from. We now show this panel when
clicking on the tracks button in the controls bar and populate its content with the
list of audio and text tracks for the media element. As an item is picked from the tracks
panel, we toggle the represented track's enabled state and dismiss the panel.

We also pick up the text track container display mostly unchanged from current media controls.

Tests: media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html
       media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html

* Modules/modern-media-controls/controls/macos-inline-media-controls.js:
(MacOSInlineMediaControls.prototype.showTracksPanel):
* Modules/modern-media-controls/controls/text-tracks.css: Added.
(video::-webkit-media-text-track-container):
(video::cue):
(video::-webkit-media-text-track-display):
(video::-webkit-media-text-track-display-backdrop):
(video::cue(:future)):
(video::-webkit-media-text-track-container b):
(video::-webkit-media-text-track-container u):
(video::-webkit-media-text-track-container i):
(video::-webkit-media-text-track-container .hidden):
* Modules/modern-media-controls/media/media-controller.js:
(MediaController):
* Modules/modern-media-controls/media/tracks-support.js:
(TracksSupport):
(TracksSupport.prototype.destroy):
(TracksSupport.prototype.buttonWasClicked):
(TracksSupport.prototype.tracksPanelNumberOfSections):
(TracksSupport.prototype.tracksPanelTitleForSection):
(TracksSupport.prototype.tracksPanelNumberOfTracksInSection):
(TracksSupport.prototype.tracksPanelTitleForTrackInSection):
(TracksSupport.prototype.tracksPanelIsTrackInSectionSelected):
(TracksSupport.prototype.tracksPanelSelectionDidChange):
(TracksSupport.prototype.syncControl):
(TracksSupport.prototype._textTracks):
(TracksSupport.prototype._audioTracks):
(TracksSupport.prototype._canPickAudioTracks):
(TracksSupport.prototype._canPickTextTracks):
(TracksSupport.prototype._sortedTrackList):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (209226 => 209227)


--- trunk/LayoutTests/ChangeLog	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/LayoutTests/ChangeLog	2016-12-02 02:07:35 UTC (rev 209227)
@@ -1,3 +1,19 @@
+2016-12-01  Antoine Quint  <grao...@apple.com>
+
+        [Modern Media Controls] Show and populate the tracks panel
+        https://bugs.webkit.org/show_bug.cgi?id=165284
+
+        Reviewed by Dean Jackson.
+
+        Add two new tests to check that we correctly show, populate and interact with the tracks panel.
+
+        * media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel-expected.txt: Added.
+        * media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html: Added.
+        * media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel-expected.txt: Added.
+        * media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html: Added.
+        * platform/ios-simulator/TestExpectations:
+        * platform/mac/TestExpectations:
+
 2016-12-01  Ryan Haddad  <ryanhad...@apple.com>
 
         Removing Release-only flag from flaky test http/tests/cache/disk-cache/disk-cache-request-max-stale.html

Added: trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel-expected.txt (0 => 209227)


--- trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel-expected.txt	2016-12-02 02:07:35 UTC (rev 209227)
@@ -0,0 +1,16 @@
+Clicking on a track in the tracks panel.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS media.audioTracks[1].enabled is false
+
+Clicking on the tracks button
+Clicking on second audio track in tracks panel
+Obtained change event on media audio tracks
+PASS media.audioTracks[1].enabled is true
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html (0 => 209227)


--- trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html	2016-12-02 02:07:35 UTC (rev 209227)
@@ -0,0 +1,58 @@
+<!DOCTYPE html><!-- webkit-test-runner [ enableModernMediaControls=true ] -->
+<script src=""
+<body>
+<video src="" style="width: 640px; height: 360px;" controls autoplay></video>
+<script type="text/_javascript_">
+
+window.jsTestIsAsync = true;
+
+description("Clicking on a track in the tracks panel.");
+
+const media = document.querySelector("video");
+const shadowRoot = window.internals.shadowRoot(media);
+
+media.addEventListener("play", () => {
+    media.pause();
+
+    shouldBeFalse("media.audioTracks[1].enabled");
+    debug("");
+
+    media.audioTracks.addEventListener("change", audioTracksDidChange);
+    window.requestAnimationFrame(() => {
+        clickOnTracksButton();
+        window.requestAnimationFrame(clickOnSecondAudioTrack);
+    });
+});
+
+function clickOnTracksButton()
+{
+    debug("Clicking on the tracks button");
+    const bounds = shadowRoot.lastChild.querySelector("button.tracks").getBoundingClientRect();
+    eventSender.mouseMoveTo(bounds.left + 1, bounds.top + 1);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+function clickOnSecondAudioTrack()
+{
+    debug("Clicking on second audio track in tracks panel");
+    const secondAudioTrack = shadowRoot.lastChild.querySelectorAll("li")[1];
+    const bounds = secondAudioTrack.getBoundingClientRect();
+    eventSender.mouseMoveTo(bounds.left + 1, bounds.top + 1);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+function audioTracksDidChange()
+{
+    debug("Obtained change event on media audio tracks");
+    shouldBeTrue("media.audioTracks[1].enabled");
+
+    debug("");
+    media.remove();
+    finishJSTest();
+}
+
+</script>
+<script src=""
+</body>

Added: trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel-expected.txt (0 => 209227)


--- trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel-expected.txt	2016-12-02 02:07:35 UTC (rev 209227)
@@ -0,0 +1,22 @@
+Showing and populating the tracks panel.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Audio
+  English Sound
+  French Sound
+  Spanish Sound
+
+Subtitles
+  Off
+  Auto (Recommended)
+  English Subtitles
+  French Subtitles
+  German Subtitles
+  Spanish Subtitles
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html (0 => 209227)


--- trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html	2016-12-02 02:07:35 UTC (rev 209227)
@@ -0,0 +1,46 @@
+<!DOCTYPE html><!-- webkit-test-runner [ enableModernMediaControls=true ] -->
+<script src=""
+<body>
+<video src="" style="width: 640px; height: 360px;" controls autoplay></video>
+<script type="text/_javascript_">
+
+window.jsTestIsAsync = true;
+
+description("Showing and populating the tracks panel.");
+
+const media = document.querySelector("video");
+const shadowRoot = window.internals.shadowRoot(media);
+
+media.addEventListener("play", () => {
+    media.pause();
+    window.requestAnimationFrame(() => {
+        clickOnTracksButton();
+        window.requestAnimationFrame(() => {
+            listContentsOfTracksPanel();
+            media.remove();
+            finishJSTest();
+        });
+    });
+});
+
+function clickOnTracksButton()
+{
+    const bounds = shadowRoot.lastChild.querySelector("button.tracks").getBoundingClientRect();
+    eventSender.mouseMoveTo(bounds.left + 1, bounds.top + 1);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+function listContentsOfTracksPanel()
+{
+    for (let section of shadowRoot.lastChild.querySelectorAll(".tracks-panel-section")) {
+        debug(section.querySelector("h3").textContent);
+        for (let item of section.querySelectorAll("li"))
+            debug("  " + item.textContent);
+        debug("");
+    }
+}
+
+</script>
+<script src=""
+</body>

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (209226 => 209227)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-12-02 02:07:35 UTC (rev 209227)
@@ -2741,10 +2741,11 @@
 # Only Mac has implemented DictionaryLookup
 fast/layers/prevent-hit-test-during-layout.html [ Skip ]
 
-# Internal APIs to test PiP and AirPlay are not available on iOS.
+# Internal APIs to test PiP and AirPlay are not available on iOS, and we don't support showing the tracks button on iOS.
 media/modern-media-controls/airplay-support/airplay-support.html [ Skip ]
 media/modern-media-controls/pip-support [ Skip ]
 media/modern-media-controls/placard-support [ Skip ]
+media/modern-media-controls/tracks-support [ Skip ]
 media/modern-media-controls/audio [ Skip ]
 
 # Mac-specific tests for fullscreen.

Modified: trunk/LayoutTests/platform/mac/TestExpectations (209226 => 209227)


--- trunk/LayoutTests/platform/mac/TestExpectations	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2016-12-02 02:07:35 UTC (rev 209227)
@@ -1453,6 +1453,8 @@
 [ Yosemite ] media/modern-media-controls/audio [ Skip ]
 [ Yosemite ] media/modern-media-controls/media-controller/media-controller-fullscreen-ltr.html [ Skip ]
 [ Yosemite ] media/modern-media-controls/tracks-panel/tracks-panel-select-track-with-keyboard.html [ Skip ]
+[ Yosemite ] media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html [ Skip ]
+[ Yosemite ] media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html [ Skip ]
 
 webkit.org/b/164616 http/tests/media/modern-media-controls/skip-back-support/skip-back-support-button-click.html [ Pass Failure ]
 webkit.org/b/164323 media/modern-media-controls/airplay-support/airplay-support.html [ Pass Failure ]

Modified: trunk/Source/WebCore/ChangeLog (209226 => 209227)


--- trunk/Source/WebCore/ChangeLog	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/Source/WebCore/ChangeLog	2016-12-02 02:07:35 UTC (rev 209227)
@@ -1,3 +1,52 @@
+2016-12-01  Antoine Quint  <grao...@apple.com>
+
+        [Modern Media Controls] Show and populate the tracks panel
+        https://bugs.webkit.org/show_bug.cgi?id=165284
+
+        Reviewed by Dean Jackson.
+
+        We added a TracksPanel in https://bugs.webkit.org/show_bug.cgi?id=165239 which allows to
+        show a list of media tracks and text tracks to choose from. We now show this panel when
+        clicking on the tracks button in the controls bar and populate its content with the
+        list of audio and text tracks for the media element. As an item is picked from the tracks
+        panel, we toggle the represented track's enabled state and dismiss the panel.
+
+        We also pick up the text track container display mostly unchanged from current media controls.
+
+        Tests: media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html
+               media/modern-media-controls/tracks-support/tracks-support-show-and-populate-panel.html
+
+        * Modules/modern-media-controls/controls/macos-inline-media-controls.js:
+        (MacOSInlineMediaControls.prototype.showTracksPanel):
+        * Modules/modern-media-controls/controls/text-tracks.css: Added.
+        (video::-webkit-media-text-track-container):
+        (video::cue):
+        (video::-webkit-media-text-track-display):
+        (video::-webkit-media-text-track-display-backdrop):
+        (video::cue(:future)):
+        (video::-webkit-media-text-track-container b):
+        (video::-webkit-media-text-track-container u):
+        (video::-webkit-media-text-track-container i):
+        (video::-webkit-media-text-track-container .hidden):
+        * Modules/modern-media-controls/media/media-controller.js:
+        (MediaController):
+        * Modules/modern-media-controls/media/tracks-support.js:
+        (TracksSupport):
+        (TracksSupport.prototype.destroy):
+        (TracksSupport.prototype.buttonWasClicked):
+        (TracksSupport.prototype.tracksPanelNumberOfSections):
+        (TracksSupport.prototype.tracksPanelTitleForSection):
+        (TracksSupport.prototype.tracksPanelNumberOfTracksInSection):
+        (TracksSupport.prototype.tracksPanelTitleForTrackInSection):
+        (TracksSupport.prototype.tracksPanelIsTrackInSectionSelected):
+        (TracksSupport.prototype.tracksPanelSelectionDidChange):
+        (TracksSupport.prototype.syncControl):
+        (TracksSupport.prototype._textTracks):
+        (TracksSupport.prototype._audioTracks):
+        (TracksSupport.prototype._canPickAudioTracks):
+        (TracksSupport.prototype._canPickTextTracks):
+        (TracksSupport.prototype._sortedTrackList):
+
 2016-12-01  Brent Fulgham  <bfulg...@apple.com>
 
         Rare crash when preparing to print

Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/macos-inline-media-controls.js (209226 => 209227)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/macos-inline-media-controls.js	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/macos-inline-media-controls.js	2016-12-02 02:07:35 UTC (rev 209227)
@@ -118,6 +118,12 @@
         this._volumeSliderContainer.x = this._rightContainer.x + this.muteButton.x;
     }
 
+    showTracksPanel()
+    {
+        super.showTracksPanel();
+        this.tracksPanel.rightX = this._rightContainer.width - this.tracksButton.x - this.tracksButton.width;
+    }
+
     // Protected
 
     handleEvent(event)

Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/text-tracks.css (0 => 209227)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/text-tracks.css	                        (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/text-tracks.css	2016-12-02 02:07:35 UTC (rev 209227)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+video::-webkit-media-text-track-container {
+    position: relative;
+    width: 100%;
+    bottom: 50px;
+    overflow: hidden;
+    padding-bottom: 5px;
+    z-index: 0;
+
+    text-align: center;
+    color: rgba(255, 255, 255, 1);
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-decoration: none;
+    pointer-events: none;
+    -webkit-user-select: none;
+
+    -webkit-flex: 1 1 auto;
+
+    -webkit-line-box-contain: block inline-box replaced;
+}
+
+video::cue {
+    background-color: rgba(0, 0, 0, 0.8);
+}
+
+video::-webkit-media-text-track-display {
+    position: absolute;
+    overflow: hidden;
+    white-space: pre-wrap;
+    -webkit-box-sizing: border-box;
+    font: 22px sans-serif;
+}
+
+video::-webkit-media-text-track-display-backdrop {
+    display: inline-block;
+}
+
+video::cue(:future) {
+    color: gray;
+}
+
+video::-webkit-media-text-track-container b {
+    font-weight: bold;
+}
+
+video::-webkit-media-text-track-container u {
+    text-decoration: underline;
+}
+
+video::-webkit-media-text-track-container i {
+    font-style: italic;
+}
+
+video::-webkit-media-text-track-container .hidden {
+    display: none;
+}

Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js (209226 => 209227)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2016-12-02 02:07:35 UTC (rev 209227)
@@ -32,8 +32,10 @@
         this.media = media;
         this.host = host;
 
-        if (host)
+        if (host) {
             media.addEventListener("webkitpresentationmodechanged", this);
+            shadowRoot.appendChild(host.textTrackContainer);
+        }
 
         this._updateControlsIfNeeded();
 

Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/tracks-support.js (209226 => 209227)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/tracks-support.js	2016-12-02 01:30:46 UTC (rev 209226)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/tracks-support.js	2016-12-02 02:07:35 UTC (rev 209227)
@@ -33,9 +33,12 @@
         if (!this.control)
             return;
 
+        this.mediaController.controls.tracksPanel.dataSource = this;
+        this.mediaController.controls.tracksPanel.uiDelegate = this;
+
         const media = mediaController.media;
         for (let tracks of [media.audioTracks, media.textTracks]) {
-            for (let eventType of ["addtrack", "removetrack"])
+            for (let eventType of ["addtrack", "change", "removetrack"])
                 tracks.addEventListener(eventType, this);
         }
     }
@@ -48,7 +51,7 @@
 
         const media = this.mediaController.media;
         for (let tracks of [media.audioTracks, media.textTracks]) {
-            for (let eventType of ["addtrack", "removetrack"])
+            for (let eventType of ["addtrack", "change", "removetrack"])
                 tracks.removeEventListener(eventType, this);
         }
     }
@@ -67,18 +70,100 @@
 
     buttonWasClicked(control)
     {
-        // FIXME: Show tracks menu.
+        this.mediaController.controls.showTracksPanel();
     }
 
+    tracksPanelNumberOfSections()
+    {
+        let numberOfSections = 0;
+        if (this._canPickAudioTracks())
+            numberOfSections++;
+        if (this._canPickTextTracks())
+            numberOfSections++;
+        return numberOfSections;
+    }
+
+    tracksPanelTitleForSection(sectionIndex)
+    {
+        if (sectionIndex == 0 && this._canPickAudioTracks())
+            return UIString("Audio");
+        return UIString("Subtitles");
+    }
+
+    tracksPanelNumberOfTracksInSection(sectionIndex)
+    {
+        if (sectionIndex == 0 && this._canPickAudioTracks())
+            return this._audioTracks().length;
+        return this._textTracks().length;
+    }
+
+    tracksPanelTitleForTrackInSection(trackIndex, sectionIndex)
+    {
+        let track;
+        if (sectionIndex == 0 && this._canPickAudioTracks())
+            track = this._audioTracks()[trackIndex];
+        else
+            track = this._textTracks()[trackIndex];
+
+        if (this.mediaController.host)
+            return this.mediaController.host.displayNameForTrack(track);
+        return track.label;
+    }
+
+    tracksPanelIsTrackInSectionSelected(trackIndex, sectionIndex)
+    {
+        if (sectionIndex == 0 && this._canPickAudioTracks())
+            return this._audioTracks()[trackIndex].enabled;
+        return this._textTracks()[trackIndex].mode !== "disabled";
+    }
+
+    tracksPanelSelectionDidChange(trackIndex, sectionIndex)
+    {
+        if (sectionIndex == 0 && this._canPickAudioTracks()) {
+            let track = this._audioTracks()[trackIndex];
+            track.enabled = !track.enabled;
+        } else {
+            let track = this._textTracks()[trackIndex];
+            track.mode = track.mode === "disabled" ? "showing" : "disabled";
+        }
+
+        this.mediaController.controls.hideTracksPanel();
+    }
+
     syncControl()
     {
-        const media = this.mediaController.media;
-        const host = this.mediaController.host;
+        this.control.enabled = this._canPickAudioTracks() || this._canPickTextTracks();
+    }
 
-        const textTracks = host ? host.sortedTrackListForMenu(media.textTracks) : media.textTracks;
-        const audioTracks = host ? host.sortedTrackListForMenu(media.audioTracks) : media.audioTracks;
+    // Private
 
-        this.control.enabled = (textTracks && textTracks.length > 0) || (audioTracks && audioTracks.length > 1);
+    _textTracks()
+    {
+        return this._sortedTrackList(this.mediaController.media.textTracks);
     }
 
+    _audioTracks()
+    {
+        return this._sortedTrackList(this.mediaController.media.audioTracks);
+    }
+
+    _canPickAudioTracks()
+    {
+        const audioTracks = this._audioTracks();
+        return audioTracks && audioTracks.length > 1;
+    }
+
+    _canPickTextTracks()
+    {
+        const textTracks = this._textTracks();
+        return textTracks && textTracks.length > 0;
+    }
+
+    _sortedTrackList(tracks)
+    {
+        if (this.mediaController.host)
+            return this.mediaController.host.sortedTrackListForMenu(tracks);
+        return tracks;
+    }
+
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to