Chromium Code Reviews| Index: Source/core/html/shadow/MediaControlElements.cpp |
| diff --git a/Source/core/html/shadow/MediaControlElements.cpp b/Source/core/html/shadow/MediaControlElements.cpp |
| index 3e2c7537ea26df6c70a25bb2dc7c27e768fc543f..fcb9017461725a36924fdf45c15f48810bf057f6 100644 |
| --- a/Source/core/html/shadow/MediaControlElements.cpp |
| +++ b/Source/core/html/shadow/MediaControlElements.cpp |
| @@ -33,6 +33,9 @@ |
| #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| #include "core/InputTypeNames.h" |
| #include "core/dom/DOMTokenList.h" |
| +#include "core/dom/Document.h" |
| +#include "core/dom/Element.h" |
| +#include "core/dom/Text.h" |
| #include "core/dom/shadow/ShadowRoot.h" |
| #include "core/events/MouseEvent.h" |
| #include "core/frame/LocalFrame.h" |
| @@ -40,11 +43,14 @@ |
| #include "core/html/MediaController.h" |
| #include "core/html/TimeRanges.h" |
| #include "core/html/shadow/MediaControls.h" |
| +#include "core/html/track/TextTrackList.h" |
| #include "core/layout/LayoutSlider.h" |
| #include "core/layout/LayoutTheme.h" |
| #include "core/layout/LayoutVideo.h" |
| #include "core/page/EventHandler.h" |
| +#include "platform/EventDispatchForbiddenScope.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| +#include "platform/text/PlatformLocale.h" |
| namespace blink { |
| @@ -53,6 +59,12 @@ using namespace HTMLNames; |
| // This is the duration from mediaControls.css |
| static const double fadeOutDuration = 0.3; |
| +// track index attribute specifies trackIndex for text track list elements |
| +static const char* trackIndexAttr = "x-webkit-track-index"; |
|
fs
2015/04/14 12:34:56
const char foo[] = ...
Also since this should be
srivats
2015/04/16 23:37:19
I couldn't find the data- convention used for attr
fs
2015/04/17 11:54:46
I don't think the exact name should matter much -
srivats
2015/04/21 01:48:55
Done.
|
| + |
| +// when specified as trackIndex, disable text tracks |
| +static const int trackIndexOffValue = -1; |
| + |
| static bool isUserInteractionEvent(Event* event) |
| { |
| const AtomicString& type = event->type(); |
| @@ -341,14 +353,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()); |
| - setChecked(mediaElement().closedCaptionsVisible()); |
| + mediaControls().toggleClosedCaptionsTrackList(); |
| updateDisplayType(); |
| event->setDefaultHandled(); |
| } |
| @@ -358,6 +368,145 @@ void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e |
| // ---------------------------- |
| +MediaControlClosedCaptionsTrackListContainerElement::MediaControlClosedCaptionsTrackListContainerElement(MediaControls& mediaControls) |
| + : MediaControlDivElement(mediaControls, MediaClosedCaptionsTrackListContainer) |
| +{ |
| +} |
| + |
| +PassRefPtrWillBeRawPtr<MediaControlClosedCaptionsTrackListContainerElement> |
| + MediaControlClosedCaptionsTrackListContainerElement::create(MediaControls& mediaControls) |
| +{ |
| + RefPtrWillBeRawPtr<MediaControlClosedCaptionsTrackListContainerElement> element = |
| + adoptRefWillBeNoop(new MediaControlClosedCaptionsTrackListContainerElement(mediaControls)); |
| + element->setShadowPseudoId(AtomicString("-webkit-media-controls-closed-captions-track-list-container", |
| + AtomicString::ConstructFromLiteral)); |
| + element->hide(); |
| + return element.release(); |
| +} |
| + |
| +// ---------------------------- |
| + |
| +MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement(MediaControls& mediaControls) |
| + : MediaControlDivElement(mediaControls, MediaClosedCaptionsTrackList) |
| +{ |
| +} |
| + |
| +PassRefPtrWillBeRawPtr<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(MediaControls& mediaControls) |
| +{ |
| + RefPtrWillBeRawPtr<MediaControlClosedCaptionsTrackListElement> element = |
| + adoptRefWillBeNoop(new MediaControlClosedCaptionsTrackListElement(mediaControls)); |
| + element->setShadowPseudoId(AtomicString("-webkit-media-controls-closed-captions-track-list", |
|
fs
2015/04/14 12:34:56
I think we should avoid carrying the "closed capti
srivats
2015/04/16 23:37:20
Changed it here and everywhere in this CL
|
| + AtomicString::ConstructFromLiteral)); |
| + element->hide(); |
|
fs
2015/04/14 12:34:56
The container is already hidden, so this doesn't s
srivats
2015/04/16 23:37:20
Done.
|
| + return element.release(); |
| +} |
| + |
| +void MediaControlClosedCaptionsTrackListElement::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; |
| + |
| + bool validIndex; |
| + int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(&validIndex); |
| + if (!validIndex) |
| + return; |
| + bool isVisible = trackIndex != trackIndexOffValue; |
| + if (isVisible && trackIndex >= 0) |
| + mediaElement().showTextTrackAtIndex(trackIndex); |
| + |
| + mediaElement().setClosedCaptionsVisible(isVisible); |
|
fs
2015/04/14 12:34:56
If we need to call into HTMLMediaElement (directly
srivats
2015/04/16 23:37:19
Moved showTextTrackAtIndex to this file and settin
|
| + |
| + mediaControls().toggleClosedCaptionsTrackList(); |
| + event->setDefaultHandled(); |
| + } |
| +} |
|
fs
2015/04/14 12:34:57
Call the parent class?
srivats
2015/04/16 23:37:19
Done.
|
| + |
| +String MediaControlClosedCaptionsTrackListElement::getTextTrackLabel(TextTrack* track) |
| +{ |
| + String trackLabel; |
| + |
| + if (!(track->label().isNull() || track->label().isEmpty())) { |
|
fs
2015/04/14 12:34:56
isEmpty implies isNull, so this can be simplified
srivats
2015/04/16 23:37:19
Done.
|
| + trackLabel = track->label(); |
| + } else { |
| + if (!(track->language().isNull() || track->language().isEmpty())) |
| + trackLabel = track->language(); |
| + else |
| + trackLabel = String(mediaElement().locale().queryString(WebLocalizedString::TextTracksNoLabel)); |
| + } |
| + |
| + // When the track kind is captions, add a captions marker to distinguish between captions and subtitles. |
| + if (track->kind() == track->captionsKeyword()) |
| + trackLabel.append(String(mediaElement().locale().queryString(WebLocalizedString::TextTracksCaptionsMarker))); |
|
fs
2015/04/14 12:34:56
Locale::queryString returns a String, so this cast
srivats
2015/04/16 23:37:19
Done.
|
| + return trackLabel; |
| +} |
| + |
| +RefPtrWillBeRawPtr<Element> MediaControlClosedCaptionsTrackListElement::createTextTrackListItem(const String& trackDisplayText, int trackIndex, bool isShowing) |
| +{ |
| + Document* doc = &document(); |
|
fs
2015/04/14 12:34:56
Prefer a reference. Also 'document' rather than 'd
srivats
2015/04/16 23:37:19
Changed the variable name to document and changed
|
| + RefPtrWillBeRawPtr<Element> trackItem = doc->createElement(labelTag, false); |
|
fs
2015/04/14 12:34:56
You can call the create() functions directly inste
srivats
2015/04/16 23:37:20
Calling Element::create() doesn't create an HTML e
fs
2015/04/17 11:54:46
I believe for this call it'd be HTMLLabelElement::
srivats
2015/04/21 01:48:55
Done.
|
| + trackItem->setShadowPseudoId(AtomicString("-webkit-media-controls-closed-captions-track-list-item", |
| + AtomicString::ConstructFromLiteral)); |
| + RefPtrWillBeRawPtr<Element> trackItemInput = doc->createElement(inputTag, false); |
| + trackItemInput->setShadowPseudoId(AtomicString("-webkit-media-controls-closed-captions-track-list-item-input", |
| + AtomicString::ConstructFromLiteral)); |
| + trackItemInput->setAttribute(typeAttr, InputTypeNames::radio); |
| + trackItemInput->setAttribute(nameAttr, "tracks"); |
| + trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex), ASSERT_NO_EXCEPTION); |
| + if (!mediaElement().closedCaptionsVisible()) { |
| + if (trackIndex == trackIndexOffValue) |
| + toHTMLInputElement(trackItemInput)->setChecked(true); |
| + } else { |
| + if (trackIndex >= 0 && isShowing) |
|
fs
2015/04/14 12:34:57
Looks like this means multiple tracks can be selec
srivats
2015/04/16 23:37:19
Since the track list is a list of input radio, it'
fs
2015/04/17 11:54:46
This is not guaranteed by this expression though A
srivats
2015/04/21 01:48:55
When multiple tracks are set to showing, it displa
|
| + toHTMLInputElement(trackItemInput)->setChecked(true); |
| + } |
| + trackItem->appendChild(trackItemInput); |
| + trackItem->appendChild(doc->createTextNode(trackDisplayText)); |
| + return trackItem; |
| +} |
| + |
| +void MediaControlClosedCaptionsTrackListElement::refreshTextTrackListMenu() |
| +{ |
| + if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady()) |
| + return; |
| + |
| + TextTrackList* trackList = mediaElement().textTracks(); |
| + if (!trackList || trackList->length() == 0) |
|
fs
2015/04/14 12:34:56
If hasClosedCaptions() returns true, then there'll
srivats
2015/04/16 23:37:19
Good point. Removed.
|
| + return; |
| + |
| + removeChildren(); |
| + |
| + // Construct a menu for subtitles and captions |
| + EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; |
| + Document* doc = &document(); |
| + RefPtrWillBeRawPtr<Element> tracksHeader = doc->createElement(h3Tag, false); |
| + tracksHeader->setShadowPseudoId(AtomicString("-webkit-media-controls-closed-captions-track-list-header", |
| + AtomicString::ConstructFromLiteral)); |
| + RefPtrWillBeRawPtr<Element> tracksSection = doc->createElement(divTag, false); |
| + |
| + tracksHeader->appendChild(doc->createTextNode(mediaElement().locale().queryString(WebLocalizedString::TextTracksSubtitlesCC))); |
|
fs
2015/04/14 12:34:56
What's the 'CC' suffix for - seems redundant unles
srivats
2015/04/16 23:37:19
I wasn't sure what the header should say. Safari u
fs
2015/04/17 11:54:46
Ok, so it's SubtitlesOrCaptions then. What the str
srivats
2015/04/21 01:48:55
That makes sense. I feel Subtitles And/Or Captions
fs
2015/04/21 12:13:34
Sounds OK to me.
srivats
2015/04/21 21:11:18
Done.
|
| + AtomicString tracksSectionId = AtomicString("tracks-header"); |
|
fs
2015/04/14 12:34:56
ConstructFromLiteral
srivats
2015/04/16 23:37:19
Done.
|
| + tracksHeader->setAttribute(idAttr, tracksSectionId); |
| + tracksSection->setAttribute(roleAttr, radiogroupAttr.localName()); |
| + tracksSection->setAttribute(aria_labeledbyAttr, tracksSectionId); |
| + |
| + String textTracksOffLabel = String(mediaElement().locale().queryString(WebLocalizedString::TextTracksOff)); |
|
fs
2015/04/14 12:34:56
queryString returns a String.
srivats
2015/04/16 23:37:19
Done.
|
| + tracksSection->appendChild(createTextTrackListItem(textTracksOffLabel, trackIndexOffValue, false)); |
| + |
| + for (unsigned i = 0; i < trackList->length(); i++) { |
| + TextTrack* track = trackList->item(i); |
| + RefPtrWillBeRawPtr<Element> trackItem = |
| + createTextTrackListItem(getTextTrackLabel(track), i, track->mode() == TextTrack::showingKeyword()); |
|
fs
2015/04/14 12:34:56
TextTrack::trackIndex() can already give 'i', so i
srivats
2015/04/16 23:37:19
Passing in TextTrack won't help with reusing this
fs
2015/04/17 11:54:46
I guess that's a fair point to make, although I gu
srivats
2015/04/21 01:48:55
Done.
|
| + tracksSection->appendChild(trackItem); |
| + } |
| + appendChild(tracksHeader); |
| + appendChild(tracksSection); |
| +} |
| + |
| +// ---------------------------- |
| + |
| MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls) |
| : MediaControlInputElement(mediaControls, MediaSlider) |
| { |