Skip to content
This repository has been archived by the owner on Jul 18, 2018. It is now read-only.

Commit

Permalink
[Blink, Media] Added controlsList to HTMLMediaElement
Browse files Browse the repository at this point in the history
Adds a DOMTokenList backed controlsList/controlslist attribute to HTMLMediaElement with three keywords: nodownload, nofullscreen and noremoteplayback.

Spec change is discussed here: whatwg/html#2293
Spec change PR is here: whatwg/html#2426
WICG repo for the API is here: https://github.com/WICG/controls-list
Intent to ship is here: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/tFuQd3AcsIQ/discussion

BUG=650174,685018
TEST=manual+layout tests

Review-Url: https://codereview.chromium.org/2657723002
Cr-Commit-Position: refs/heads/master@{#455926}
  • Loading branch information
avayvod authored and Commit bot committed Mar 10, 2017
1 parent 5bf97f6 commit caca068
Show file tree
Hide file tree
Showing 20 changed files with 268 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>Test adding keywords to controlsList hides buttons</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../media-resources/media-file.js"></script>
<script src="../../media-resources/media-controls.js"></script>
<video controls id="enabled-controls" width="500px"></video>
<script>
async_test(t => {
var v = document.getElementById('enabled-controls');

v.addEventListener('canplaythrough', t.step_func(e => {
assert_not_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_not_equals(getComputedStyle(downloadButton(v)).display, 'none');

v.controlsList.add('nodownload');

testRunner.layoutAndPaintAsyncThen(t.step_func(() => {
assert_not_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_equals(getComputedStyle(downloadButton(v)).display, 'none');
v.controlsList.add('nofullscreen');

testRunner.layoutAndPaintAsyncThen(t.step_func_done(() => {
assert_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_equals(getComputedStyle(downloadButton(v)).display, 'none');
}));
}));
}));

v.src = findMediaFile('video', '../resources/test');
}, 'Test disabling controls on the video element with all controls.');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>Test removing keywords from controlsList shows buttons</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../media-resources/media-file.js"></script>
<script src="../../media-resources/media-controls.js"></script>
<video controlslist="nodownload nofullscreen" id="disabled-controls" width="500px"></video>
<script>
async_test(t => {
var v = document.getElementById('disabled-controls');

v.addEventListener('canplaythrough', t.step_func(e => {
assert_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_equals(getComputedStyle(downloadButton(v)).display, 'none');

v.controlsList.remove('nodownload');

testRunner.layoutAndPaintAsyncThen(t.step_func(() => {
assert_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_not_equals(getComputedStyle(downloadButton(v)).display, 'none');

v.controlsList.remove('nofullscreen');

testRunner.layoutAndPaintAsyncThen(t.step_func_done(() => {
assert_not_equals(getComputedStyle(fullscreenButton(v)).display, 'none');
assert_not_equals(getComputedStyle(downloadButton(v)).display, 'none');
}));
}));
}));

v.src = findMediaFile('video', '../resources/test');
}, 'Test enabling controls on the video element with them enabled.');
</script>

16 changes: 16 additions & 0 deletions third_party/WebKit/LayoutTests/media/media-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ function castButton(videoElement) {
return button;
}

function downloadButton(videoElement) {
var controlID = '-internal-media-controls-download-button';
var button = mediaControlsElement(window.internals.shadowRoot(videoElement).firstChild, controlID);
if (!button)
throw 'Failed to find download button';
return button;
}

function fullscreenButton(videoElement) {
var controlID = '-webkit-media-controls-fullscreen-button';
var button = mediaControlsElement(window.internals.shadowRoot(videoElement).firstChild, controlID);
if (!button)
throw 'Failed to find fullscreen button';
return button;
}

function overlayCastButton(videoElement)
{
var controlID = '-internal-media-controls-overlay-cast-button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,7 @@ interface HTMLMediaElement : HTMLElement
getter autoplay
getter buffered
getter controls
getter controlsList
getter crossOrigin
getter currentSrc
getter currentTime
Expand Down Expand Up @@ -2379,6 +2380,7 @@ interface HTMLMediaElement : HTMLElement
method setSinkId
setter autoplay
setter controls
setter controlsList
setter crossOrigin
setter currentTime
setter defaultMuted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,7 @@ interface HTMLMediaElement : HTMLElement
getter autoplay
getter buffered
getter controls
getter controlsList
getter crossOrigin
getter currentSrc
getter currentTime
Expand Down Expand Up @@ -2308,6 +2309,7 @@ interface HTMLMediaElement : HTMLElement
method setSinkId
setter autoplay
setter controls
setter controlsList
setter crossOrigin
setter currentTime
setter defaultMuted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ html element audio
property buffered
property canPlayType
property controls
property controlsList
property crossOrigin
property currentSrc
property currentTime
Expand Down Expand Up @@ -1019,6 +1020,7 @@ html element video
property buffered
property canPlayType
property controls
property controlsList
property crossOrigin
property currentSrc
property currentTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ html element audio
property canPlayType
property captureStream
property controls
property controlsList
property crossOrigin
property currentSrc
property currentTime
Expand Down Expand Up @@ -1049,6 +1050,7 @@ html element video
property canPlayType
property captureStream
property controls
property controlsList
property crossOrigin
property currentSrc
property currentTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2884,6 +2884,7 @@ interface HTMLMediaElement : HTMLElement
getter autoplay
getter buffered
getter controls
getter controlsList
getter crossOrigin
getter currentSrc
getter currentTime
Expand Down Expand Up @@ -2926,6 +2927,7 @@ interface HTMLMediaElement : HTMLElement
method setSinkId
setter autoplay
setter controls
setter controlsList
setter crossOrigin
setter currentTime
setter defaultMuted
Expand Down
4 changes: 4 additions & 0 deletions third_party/WebKit/Source/core/frame/UseCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,10 @@ class CORE_EXPORT UseCounter {
GetCanvas2DContextAttributes = 1850,
V8HTMLInputElement_Capture_AttributeGetter = 1851,
V8HTMLInputElement_Capture_AttributeSetter = 1852,
HTMLMediaElementControlsListAttribute = 1853,
HTMLMediaElementControlsListNoDownload = 1854,
HTMLMediaElementControlsListNoFullscreen = 1855,
HTMLMediaElementControlsListNoRemotePlayback = 1856,

// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
Expand Down
2 changes: 2 additions & 0 deletions third_party/WebKit/Source/core/html/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ blink_core_sources("html") {
"HTMLMarqueeElement.cpp",
"HTMLMarqueeElement.h",
"HTMLMediaElement.cpp",
"HTMLMediaElementControlsList.cpp",
"HTMLMediaElementControlsList.h",
"HTMLMediaSource.cpp",
"HTMLMediaSource.h",
"HTMLMenuElement.cpp",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"contenteditable",
"contextmenu",
"controls",
"controlslist",
"coords",
"crossorigin",
"csp",
Expand Down
25 changes: 24 additions & 1 deletion third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName,
m_autoplayUmaHelper(AutoplayUmaHelper::create(this)),
m_remotePlaybackClient(nullptr),
m_autoplayVisibilityObserver(nullptr),
m_mediaControls(nullptr) {
m_mediaControls(nullptr),
m_controlsList(HTMLMediaElementControlsList::create(this)) {
BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";

m_lockedPendingUserGesture = computeLockedPendingUserGesture(document);
Expand Down Expand Up @@ -598,6 +599,14 @@ void HTMLMediaElement::parseAttribute(
UseCounter::count(document(),
UseCounter::HTMLMediaElementControlsAttribute);
updateControlsVisibility();
} else if (name == controlslistAttr) {
UseCounter::count(document(),
UseCounter::HTMLMediaElementControlsListAttribute);
if (params.oldValue != params.newValue) {
m_controlsList->setValue(params.newValue);
if (mediaControls())
mediaControls()->onControlsListUpdated();
}
} else if (name == preloadAttr) {
setPlayerPreload();
} else if (name == disableremoteplaybackAttr) {
Expand Down Expand Up @@ -2437,6 +2446,19 @@ bool HTMLMediaElement::shouldShowControls(
return false;
}

HTMLMediaElementControlsList* HTMLMediaElement::controlsList() const {
return m_controlsList.get();
}

void HTMLMediaElement::controlsListValueWasSet() {
if (fastGetAttribute(controlslistAttr) == m_controlsList->value())
return;

setSynchronizedLazyAttribute(controlslistAttr, m_controlsList->value());
if (mediaControls())
mediaControls()->onControlsListUpdated();
}

double HTMLMediaElement::volume() const {
return m_volume;
}
Expand Down Expand Up @@ -3823,6 +3845,7 @@ DEFINE_TRACE(HTMLMediaElement) {
visitor->trace(m_srcObject);
visitor->trace(m_autoplayVisibilityObserver);
visitor->trace(m_mediaControls);
visitor->trace(m_controlsList);
visitor->template registerWeakMembers<HTMLMediaElement,
&HTMLMediaElement::clearWeakMembers>(
this);
Expand Down
6 changes: 5 additions & 1 deletion third_party/WebKit/Source/core/html/HTMLMediaElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#ifndef HTMLMediaElement_h
#define HTMLMediaElement_h

#include <memory>
#include "bindings/core/v8/ActiveScriptWrappable.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/TraceWrapperMember.h"
Expand All @@ -35,14 +36,14 @@
#include "core/dom/SuspendableObject.h"
#include "core/events/GenericEventQueue.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLMediaElementControlsList.h"
#include "core/html/track/TextTrack.h"
#include "platform/Supplementable.h"
#include "platform/WebTaskRunner.h"
#include "platform/audio/AudioSourceProvider.h"
#include "platform/network/mime/MIMETypeRegistry.h"
#include "public/platform/WebAudioSourceProviderClient.h"
#include "public/platform/WebMediaPlayerClient.h"
#include <memory>

namespace blink {

Expand Down Expand Up @@ -202,6 +203,8 @@ class CORE_EXPORT HTMLMediaElement
// controls
bool shouldShowControls(
const RecordMetricsBehavior = RecordMetricsBehavior::DoNotRecord) const;
HTMLMediaElementControlsList* controlsList() const;
void controlsListValueWasSet();
double volume() const;
void setVolume(double, ExceptionState& = ASSERT_NO_EXCEPTION);
bool muted() const;
Expand Down Expand Up @@ -749,6 +752,7 @@ class CORE_EXPORT HTMLMediaElement
IntRect m_currentIntersectRect;

Member<MediaControls> m_mediaControls;
Member<HTMLMediaElementControlsList> m_controlsList;

static URLRegistry* s_mediaStreamRegistry;
};
Expand Down
2 changes: 2 additions & 0 deletions third_party/WebKit/Source/core/html/HTMLMediaElement.idl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };

// controls
[CEReactions, Reflect] attribute boolean controls;
// Spec: https://wicg.github.io/controls-list/html-output/multipage/embedded-content.html#attr-media-controlslist
[SameObject, PutForwards=value] readonly attribute DOMTokenList controlsList;
[RaisesException=Setter] attribute double volume;
attribute boolean muted;
[CEReactions, Reflect=muted] attribute boolean defaultMuted;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/html/HTMLMediaElementControlsList.h"

#include "core/html/HTMLMediaElement.h"

namespace blink {

namespace {

const char kNoDownload[] = "nodownload";
const char kNoFullscreen[] = "nofullscreen";
const char kNoRemotePlayback[] = "noremoteplayback";

const char* kSupportedTokens[] = {kNoDownload, kNoFullscreen,
kNoRemotePlayback};

} // namespace

HTMLMediaElementControlsList::HTMLMediaElementControlsList(
HTMLMediaElement* element)
: DOMTokenList(this), m_element(element) {}

HTMLMediaElementControlsList::~HTMLMediaElementControlsList() = default;

DEFINE_TRACE(HTMLMediaElementControlsList) {
visitor->trace(m_element);
DOMTokenList::trace(visitor);
DOMTokenListObserver::trace(visitor);
}

bool HTMLMediaElementControlsList::validateTokenValue(
const AtomicString& tokenValue,
ExceptionState&) const {
for (const char* supportedToken : kSupportedTokens) {
if (tokenValue == supportedToken)
return true;
}
return false;
}

void HTMLMediaElementControlsList::valueWasSet() {
m_element->controlsListValueWasSet();
}

bool HTMLMediaElementControlsList::shouldHideDownload() const {
return tokens().contains(kNoDownload);
}

bool HTMLMediaElementControlsList::shouldHideFullscreen() const {
return tokens().contains(kNoFullscreen);
}

bool HTMLMediaElementControlsList::shouldHideRemotePlayback() const {
return tokens().contains(kNoRemotePlayback);
}

} // namespace blink
Loading

0 comments on commit caca068

Please sign in to comment.