Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Unified Diff: third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp

Issue 1079323002: Support text track selection in video controls (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments from fs Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
index 5b76bf6d3707991fe1b5bf843422099fec2b5876..8cebe2b53b3e355630e18c143f1923853ea48468 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -32,18 +32,25 @@
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/InputTypeNames.h"
#include "core/dom/ClientRect.h"
+#include "core/dom/Document.h"
+#include "core/dom/Text.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/MouseEvent.h"
#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLLabelElement.h"
+#include "core/html/HTMLSpanElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/html/TimeRanges.h"
#include "core/html/shadow/MediaControls.h"
+#include "core/html/track/TextTrackList.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutSlider.h"
#include "core/layout/LayoutTheme.h"
#include "core/layout/LayoutVideo.h"
#include "platform/Histogram.h"
#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/text/PlatformLocale.h"
+#include "public/platform/Platform.h"
namespace blink {
@@ -54,6 +61,16 @@ namespace {
// This is the duration from mediaControls.css
const double fadeOutDuration = 0.3;
+static const QualifiedName& trackIndexAttrName()
philipj_slow 2016/03/01 13:01:16 This is inside an anonymous namespace, so the stat
srivats 2016/03/30 00:46:43 Done.
+{
+ // Save the track index in an attribute to avoid holding a pointer to the text track element.
philipj_slow 2016/03/01 13:01:16 Remove "element"? Presumably the alternative would
srivats 2016/03/30 00:46:43 Done.
+ DEFINE_STATIC_LOCAL(QualifiedName, trackIndexAttr, (nullAtom, "data-track-index", nullAtom));
+ return trackIndexAttr;
+}
+
+// When specified as trackIndex, disable text tracks.
+static const int trackIndexOffValue = -1;
+
bool isUserInteractionEvent(Event* event)
{
const AtomicString& type = event->type();
@@ -353,14 +370,12 @@ void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
{
bool captionsVisible = mediaElement().closedCaptionsVisible();
setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
- setChecked(captionsVisible);
}
void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == EventTypeNames::click) {
- mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVisible());
philipj_slow 2016/03/01 08:51:40 This was the only call site, can you remove HTMLMe
srivats 2016/03/30 00:46:43 Done.
- setChecked(mediaElement().closedCaptionsVisible());
+ mediaControls().toggleTextTrackList();
updateDisplayType();
event->setDefaultHandled();
}
@@ -370,6 +385,151 @@ void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e
// ----------------------------
+MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls& mediaControls)
+ : MediaControlDivElement(mediaControls, MediaTextTrackList)
+{
+}
+
+PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackListElement::create(MediaControls& mediaControls)
+{
+ RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element =
+ adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls));
+ element->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list",
+ AtomicString::ConstructFromLiteral));
+ element->setIsWanted(false);
+ return element.release();
+}
+
+void MediaControlTextTrackListElement::defaultEventHandler(Event* event)
+{
+ if (event->type() == EventTypeNames::change) {
+ // Identify which input element was selected and set track to showing
+ Node* target = event->target()->toNode();
+ if (!target || !target->isElementNode())
+ return;
+
+ int trackIndex = toElement(target)->getIntegralAttribute(trackIndexAttrName());
philipj_slow 2016/03/01 13:01:16 Nit: Can you switch the order of this and the foll
srivats 2016/03/30 00:46:43 Done.
+ disableShowingTextTracks();
+ if (trackIndex != trackIndexOffValue) {
+ showTextTrackAtIndex(trackIndex);
philipj_slow 2016/03/01 13:01:16 trackIndex is int but this takes unsigned. ASSERT(
srivats 2016/03/30 00:46:43 Done.
+ mediaElement().disableAutomaticTextTrackSelection();
philipj_slow 2016/03/01 13:01:16 If a script implements its own track selection men
srivats 2016/03/30 00:46:43 I tried it and it seems to be working with some ma
+ }
+
+ mediaControls().toggleTextTrackList();
+ event->setDefaultHandled();
+ }
+ MediaControlDivElement::defaultEventHandler(event);
+}
+
+void MediaControlTextTrackListElement::changeVisibility(bool isHidden)
+{
+ if (isHidden) {
+ setIsWanted(true);
+ refreshTextTrackListMenu();
+ } else {
+ setIsWanted(false);
+ }
+}
+
+void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned indexToEnable)
+{
+ TextTrackList* trackList = mediaElement().textTracks();
+ if (trackList->length() == 0)
philipj_slow 2016/03/01 13:01:16 TextTrackList::anonymousIndexedGetter already hand
srivats 2016/03/30 00:46:43 Done.
+ return;
+ if (indexToEnable >= trackList->length())
+ return;
+ TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable);
+ if (track->canBeRendered())
+ track->setMode(TextTrack::showingKeyword());
+}
+
+void MediaControlTextTrackListElement::disableShowingTextTracks()
+{
+ TextTrackList* trackList = mediaElement().textTracks();
+ for (unsigned i = 0; i < trackList->length(); ++i) {
+ TextTrack* track = trackList->anonymousIndexedGetter(i);
+ if (track->mode() == TextTrack::showingKeyword())
+ track->setMode(TextTrack::disabledKeyword());
+ }
+}
+
+String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track)
+{
+ if (!track)
+ return mediaElement().locale().queryString(WebLocalizedString::TextTracksOff);
+
+ String trackLabel = track->label();
+
+ if (trackLabel.isEmpty())
+ trackLabel = track->language();
philipj_slow 2016/03/01 13:01:16 This was discussed in https://codereview.chromium.
srivats 2016/03/30 00:46:43 Apologies for that. I tried to respond back to as
+
+ if (trackLabel.isEmpty())
+ trackLabel = String(mediaElement().locale().queryString(WebLocalizedString::TextTracksNoLabel));
+
+ return trackLabel;
+}
+
+// TextTrack parameter when passed in as a nullptr, creates the "Off" list item in the track list.
+PassRefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrackListItem(TextTrack* track)
+{
+ Document& document = this->document();
+ int trackIndex = track ? track->trackIndex() : trackIndexOffValue;
+ RefPtrWillBeRawPtr<HTMLLabelElement> trackItem = HTMLLabelElement::create(document, 0);
philipj_slow 2016/03/01 13:01:16 s/0/nullptr/
srivats 2016/03/30 00:46:43 Done.
+ trackItem->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-item",
+ AtomicString::ConstructFromLiteral));
+ RefPtrWillBeRawPtr<HTMLInputElement> trackItemInput = HTMLInputElement::create(document, 0, false);
philipj_slow 2016/03/01 13:01:16 s/0/nullptr/
srivats 2016/03/30 00:46:43 Done.
+ trackItemInput->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-item-input",
+ AtomicString::ConstructFromLiteral));
+ trackItemInput->setType(InputTypeNames::radio);
philipj_slow 2016/03/01 13:01:16 Radio seems semantically accurate in the normal ca
srivats 2016/03/30 00:46:43 I started off with radio in a radio group but even
+ trackItemInput->setIntegralAttribute(trackIndexAttrName(), trackIndex);
+ if (!mediaElement().closedCaptionsVisible()) {
philipj_slow 2016/03/01 13:01:16 This is now not terribly accurate, it's something
srivats 2016/03/30 00:46:43 Renamed closedCaptionsVisible to textTracksVisible
+ if (!track)
+ trackItemInput->setChecked(true);
+ } else {
+ // If there are multiple text tracks set to showing, they must all have
+ // checkmarks displayed.
+ if (track && track->mode() == TextTrack::showingKeyword())
+ trackItemInput->setChecked(true);
+ }
+ RefPtrWillBeRawPtr<HTMLSpanElement> trackKindMarker = HTMLSpanElement::create(document);
+ if (track && track->kind() == track->captionsKeyword()) {
+ trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-kind-captions",
+ AtomicString::ConstructFromLiteral));
+ } else if (track && track->kind() == track->subtitlesKeyword()) {
philipj_slow 2016/03/01 13:01:16 Can you use an else branch and ASSERT(track->kind(
srivats 2016/03/30 00:46:43 Done.
+ trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-kind-subtitles",
+ AtomicString::ConstructFromLiteral));
+ }
+ trackItem->appendChild(trackItemInput);
+ trackItem->appendChild(Text::create(document, getTextTrackLabel(track)));
+ trackItem->appendChild(trackKindMarker);
+ return trackItem;
+}
+
+void MediaControlTextTrackListElement::refreshTextTrackListMenu()
+{
+ if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady())
+ return;
+
+ removeChildren(OmitSubtreeModifiedEvent);
+
+ // Construct a menu for subtitles and captions
+ RefPtrWillBeRawPtr<HTMLDivElement> tracksSection = HTMLDivElement::create(this->document());
philipj_slow 2016/03/01 13:01:16 This div element doesn't seem to be included in th
srivats 2016/03/30 00:46:43 Since we don't need a div element that holds both
+ tracksSection->setAttribute(roleAttr, radiogroupAttr.localName());
philipj_slow 2016/03/01 13:01:16 Does this change how this looks to a11y tools, and
srivats 2016/03/30 00:46:43 Got rid of the radio and hence this too
+ // Pass in a nullptr to createTextTrackListItem to create the "Off" track item.
+ tracksSection->appendChild(createTextTrackListItem(nullptr));
+
+ TextTrackList* trackList = mediaElement().textTracks();
+ for (unsigned i = 0; i < trackList->length(); i++) {
+ TextTrack* track = trackList->anonymousIndexedGetter(i);
+ if (!track->canBeRendered())
+ continue;
+ tracksSection->appendChild(createTextTrackListItem(track));
+ }
+ appendChild(tracksSection);
+}
+
+// ----------------------------
+
MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls)
: MediaControlInputElement(mediaControls, MediaSlider)
{

Powered by Google App Engine
This is Rietveld 408576698