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 c66ef9e0741eaa2fc9ac05c002b2042be9c8fdac..90e9aa90e11a11ab687e872cf96097a2507cec2d 100644 |
| --- a/Source/core/html/shadow/MediaControlElements.cpp |
| +++ b/Source/core/html/shadow/MediaControlElements.cpp |
| @@ -33,19 +33,27 @@ |
| #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/Fullscreen.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/HTMLHeadingElement.h" |
| +#include "core/html/HTMLLabelElement.h" |
| #include "core/html/HTMLVideoElement.h" |
| #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 { |
| @@ -54,6 +62,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 |
|
philipj_slow
2015/05/05 14:36:57
This comment doesn't explain what this is for. AFA
srivats
2016/02/23 01:39:26
Done.
|
| +static const char trackIndexAttr[] = "data-webkit-track-index"; |
|
philipj_slow
2015/05/05 14:36:57
Since the element is inaccessible to the outside,
srivats
2016/02/23 01:39:27
Done.
|
| + |
| +// when specified as trackIndex, disable text tracks |
|
philipj_slow
2015/05/05 14:36:57
Is a special value really needed for this, couldn'
srivats
2016/02/23 01:39:26
The -1 id helps with testing mostly to track the "
|
| +static const int trackIndexOffValue = -1; |
| + |
| static bool isUserInteractionEvent(Event* event) |
| { |
| const AtomicString& type = event->type(); |
| @@ -342,14 +356,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().toggleTextTrackList(); |
| updateDisplayType(); |
| event->setDefaultHandled(); |
| } |
| @@ -359,6 +371,142 @@ 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->hide(); |
| + 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; |
| + |
| + bool validIndex; |
| + int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(&validIndex); |
| + ASSERT(validIndex); |
| + if (trackIndex != trackIndexOffValue) { |
| + showTextTrackAtIndex(trackIndex); |
|
philipj_slow
2015/05/05 14:36:56
What happens if the text tracks change while this
srivats
2016/02/23 01:39:27
I tested this out by removing a track using the co
philipj_slow
2016/03/01 11:21:04
Refreshing the menu also seems wrong, maybe the us
|
| + mediaElement().setClosedCaptionsVisible(true); |
|
philipj_slow
2015/05/05 14:36:57
I think setClosedCaptionsVisible() needs to change
fs
2015/05/05 15:32:44
I agree with this, but I think we need a "step" in
philipj_slow
2015/05/06 09:28:43
Ahem, will get to that review too...
srivats
2016/02/23 01:39:27
Not using setClosedCaptionsVisible anymore and it'
|
| + } else { |
| + mediaElement().setClosedCaptionsVisible(false); |
| + } |
| + |
| + mediaControls().toggleTextTrackList(); |
| + event->setDefaultHandled(); |
| + } |
| + HTMLDivElement::defaultEventHandler(event); |
| +} |
| + |
| +void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned indexToEnable) |
| +{ |
| + TextTrackList* trackList = mediaElement().textTracks(); |
| + for (unsigned i = 0; i < trackList->length(); ++i) { |
| + TextTrack* track = trackList->item(i); |
| + if (!track->isRenderable()) |
|
philipj_slow
2015/05/05 14:36:57
Is this really needed?
fs
2015/05/05 15:32:44
I probably suggested this in one of the earlier CL
|
| + continue; |
| + if (i == indexToEnable && indexToEnable < trackList->length()) { |
|
philipj_slow
2015/05/05 14:36:57
The indexToEnable < trackList->length() check coul
srivats
2016/02/23 01:39:27
Done.
|
| + track->setMode(TextTrack::showingKeyword()); |
| + mediaElement().disableAutomaticTextTrackSelection(); |
|
philipj_slow
2015/05/05 14:36:57
This is the bit I'm saying should happen the same
|
| + } else 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
2015/05/05 14:36:56
This seems risky. People could use <track srclang=
fs
2015/05/05 15:32:44
ICU quite possibly have that data already. No idea
|
| + |
| + if (trackLabel.isEmpty()) |
| + trackLabel = String(mediaElement().locale().queryString(WebLocalizedString::TextTracksNoLabel)); |
| + |
| + // When the track kind is captions, add a captions marker to distinguish between captions and subtitles. |
|
philipj_slow
2015/05/05 14:36:57
I'm not sure this will make sense in all languages
fs
2015/05/05 15:32:44
Since it is localized, it could well be "" for Swe
srivats
2016/02/23 01:39:27
UX suggested I use icons here to differentiate bet
philipj_slow
2016/03/01 11:21:04
And I really like that new subtitles icon!
|
| + if (track->kind() == track->captionsKeyword()) |
| + trackLabel.append(mediaElement().locale().queryString(WebLocalizedString::TextTracksCaptionsMarker)); |
| + return trackLabel; |
| +} |
| + |
| +RefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrackListItem(TextTrack* track) |
|
philipj_slow
2015/05/05 14:36:57
This is a bit hard to understand, what does it mea
fs
2015/05/05 15:32:44
I believe I suggested to pass a track, because the
philipj_slow
2015/05/06 09:28:43
Sorry, I skipped the history and comments, so we'r
srivats
2016/02/23 01:39:26
Added a comment explaining what the nullptr is for
|
| +{ |
| + Document& document = this->document(); |
| + int trackIndex = track ? track->trackIndex() : trackIndexOffValue; |
| + RefPtrWillBeRawPtr<HTMLLabelElement> trackItem = HTMLLabelElement::create(document, 0); |
| + trackItem->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-item", |
| + AtomicString::ConstructFromLiteral)); |
| + RefPtrWillBeRawPtr<HTMLInputElement> trackItemInput = HTMLInputElement::create(document, 0, false); |
| + trackItemInput->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-item-input", |
| + AtomicString::ConstructFromLiteral)); |
| + trackItemInput->setType(InputTypeNames::radio); |
| + trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex), ASSERT_NO_EXCEPTION); |
| + if (!mediaElement().closedCaptionsVisible()) { |
| + if (!track) |
| + trackItemInput->setChecked(true); |
| + } else { |
| + if (track && track->mode() == TextTrack::showingKeyword()) |
|
philipj_slow
2015/05/05 14:36:57
If there are multiple tracks showing, I guess they
srivats
2016/02/23 01:39:27
Yes. I tested this case out.
|
| + trackItemInput->setChecked(true); |
| + } |
| + trackItem->appendChild(trackItemInput); |
| + trackItem->appendChild(Text::create(document, getTextTrackLabel(track))); |
| + return trackItem; |
| +} |
| + |
| +void MediaControlTextTrackListElement::refreshTextTrackListMenu() |
| +{ |
| + DEFINE_STATIC_LOCAL(const AtomicString, tracksSectionId, ("tracks-header", AtomicString::ConstructFromLiteral)); |
| + if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady()) |
| + return; |
| + |
| + removeChildren(); |
| + |
| + // Construct a menu for subtitles and captions |
| + EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; |
| + Document& document = this->document(); |
| + RefPtrWillBeRawPtr<HTMLHeadingElement> tracksHeader = HTMLHeadingElement::create(h3Tag, document); |
| + tracksHeader->setShadowPseudoId(AtomicString("-internal-media-controls-text-track-list-header", |
| + AtomicString::ConstructFromLiteral)); |
| + RefPtrWillBeRawPtr<HTMLDivElement> tracksSection = HTMLDivElement::create(document); |
| + |
| + tracksHeader->appendChild(Text::create(document, |
| + mediaElement().locale().queryString(WebLocalizedString::TextTracksSubtitles))); |
|
philipj_slow
2015/05/05 14:36:57
Is this line needed at all? Even if it were change
srivats
2016/02/23 01:39:27
I got some UX feedback on this and they're fine wi
|
| + tracksHeader->setAttribute(idAttr, tracksSectionId); |
| + tracksSection->setAttribute(roleAttr, radiogroupAttr.localName()); |
| + tracksSection->setAttribute(aria_labeledbyAttr, tracksSectionId); |
|
philipj_slow
2015/05/05 14:36:56
Won't we end up with multiple elements with the sa
fs
2015/05/05 15:32:44
I think it would be weird if it wasn't scoped...
philipj_slow
2015/05/06 09:28:43
Yeah, it certainly would be, just want to make sur
srivats
2016/02/23 01:39:27
No more header.
|
| + |
| + tracksSection->appendChild(createTextTrackListItem(nullptr)); |
|
philipj_slow
2015/05/05 14:36:57
So this is where it looks a bit weird. Maybe if th
srivats
2016/02/23 01:39:26
I added a comment explaining what the nullptr is f
|
| + |
| + TextTrackList* trackList = mediaElement().textTracks(); |
| + for (unsigned i = 0; i < trackList->length(); i++) { |
| + TextTrack* track = trackList->item(i); |
| + if (!track->isRenderable()) |
| + continue; |
| + RefPtrWillBeRawPtr<Element> trackItem = createTextTrackListItem(track); |
| + tracksSection->appendChild(trackItem); |
| + } |
| + appendChild(tracksHeader); |
| + appendChild(tracksSection); |
| +} |
| + |
| +// ---------------------------- |
| + |
| MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls) |
| : MediaControlInputElement(mediaControls, MediaSlider) |
| { |