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

Side by Side 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, 9 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 14 matching lines...) Expand all
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30 #include "core/html/shadow/MediaControlElements.h" 30 #include "core/html/shadow/MediaControlElements.h"
31 31
32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
33 #include "core/InputTypeNames.h" 33 #include "core/InputTypeNames.h"
34 #include "core/dom/ClientRect.h" 34 #include "core/dom/ClientRect.h"
35 #include "core/dom/Document.h"
36 #include "core/dom/Text.h"
35 #include "core/dom/shadow/ShadowRoot.h" 37 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/events/MouseEvent.h" 38 #include "core/events/MouseEvent.h"
37 #include "core/frame/LocalFrame.h" 39 #include "core/frame/LocalFrame.h"
40 #include "core/html/HTMLLabelElement.h"
41 #include "core/html/HTMLSpanElement.h"
38 #include "core/html/HTMLVideoElement.h" 42 #include "core/html/HTMLVideoElement.h"
39 #include "core/html/TimeRanges.h" 43 #include "core/html/TimeRanges.h"
40 #include "core/html/shadow/MediaControls.h" 44 #include "core/html/shadow/MediaControls.h"
45 #include "core/html/track/TextTrackList.h"
41 #include "core/input/EventHandler.h" 46 #include "core/input/EventHandler.h"
42 #include "core/layout/LayoutSlider.h" 47 #include "core/layout/LayoutSlider.h"
43 #include "core/layout/LayoutTheme.h" 48 #include "core/layout/LayoutTheme.h"
44 #include "core/layout/LayoutVideo.h" 49 #include "core/layout/LayoutVideo.h"
45 #include "platform/Histogram.h" 50 #include "platform/Histogram.h"
46 #include "platform/RuntimeEnabledFeatures.h" 51 #include "platform/RuntimeEnabledFeatures.h"
52 #include "platform/text/PlatformLocale.h"
53 #include "public/platform/Platform.h"
47 54
48 namespace blink { 55 namespace blink {
49 56
50 using namespace HTMLNames; 57 using namespace HTMLNames;
51 58
52 namespace { 59 namespace {
53 60
54 // This is the duration from mediaControls.css 61 // This is the duration from mediaControls.css
55 const double fadeOutDuration = 0.3; 62 const double fadeOutDuration = 0.3;
56 63
64 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.
65 {
66 // Save the track index in an attribute to avoid holding a pointer to the te xt track element.
philipj_slow 2016/03/01 13:01:16 Remove "element"? Presumably the alternative would
srivats 2016/03/30 00:46:43 Done.
67 DEFINE_STATIC_LOCAL(QualifiedName, trackIndexAttr, (nullAtom, "data-track-in dex", nullAtom));
68 return trackIndexAttr;
69 }
70
71 // When specified as trackIndex, disable text tracks.
72 static const int trackIndexOffValue = -1;
73
57 bool isUserInteractionEvent(Event* event) 74 bool isUserInteractionEvent(Event* event)
58 { 75 {
59 const AtomicString& type = event->type(); 76 const AtomicString& type = event->type();
60 return type == EventTypeNames::mousedown 77 return type == EventTypeNames::mousedown
61 || type == EventTypeNames::mouseup 78 || type == EventTypeNames::mouseup
62 || type == EventTypeNames::click 79 || type == EventTypeNames::click
63 || type == EventTypeNames::dblclick 80 || type == EventTypeNames::dblclick
64 || event->isKeyboardEvent() 81 || event->isKeyboardEvent()
65 || event->isTouchEvent(); 82 || event->isTouchEvent();
66 } 83 }
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 button->setType(InputTypeNames::button); 363 button->setType(InputTypeNames::button);
347 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral)); 364 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral));
348 button->setIsWanted(false); 365 button->setIsWanted(false);
349 return button.release(); 366 return button.release();
350 } 367 }
351 368
352 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() 369 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
353 { 370 {
354 bool captionsVisible = mediaElement().closedCaptionsVisible(); 371 bool captionsVisible = mediaElement().closedCaptionsVisible();
355 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton); 372 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton);
356 setChecked(captionsVisible);
357 } 373 }
358 374
359 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent) 375 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent)
360 { 376 {
361 if (event->type() == EventTypeNames::click) { 377 if (event->type() == EventTypeNames::click) {
362 mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVi sible()); 378 mediaControls().toggleTextTrackList();
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.
363 setChecked(mediaElement().closedCaptionsVisible());
364 updateDisplayType(); 379 updateDisplayType();
365 event->setDefaultHandled(); 380 event->setDefaultHandled();
366 } 381 }
367 382
368 HTMLInputElement::defaultEventHandler(event); 383 HTMLInputElement::defaultEventHandler(event);
369 } 384 }
370 385
371 // ---------------------------- 386 // ----------------------------
372 387
388 MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls & mediaControls)
389 : MediaControlDivElement(mediaControls, MediaTextTrackList)
390 {
391 }
392
393 PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackLi stElement::create(MediaControls& mediaControls)
394 {
395 RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element =
396 adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls));
397 element->setShadowPseudoId(AtomicString("-internal-media-controls-text-track -list",
398 AtomicString::ConstructFromLiteral));
399 element->setIsWanted(false);
400 return element.release();
401 }
402
403 void MediaControlTextTrackListElement::defaultEventHandler(Event* event)
404 {
405 if (event->type() == EventTypeNames::change) {
406 // Identify which input element was selected and set track to showing
407 Node* target = event->target()->toNode();
408 if (!target || !target->isElementNode())
409 return;
410
411 int trackIndex = toElement(target)->getIntegralAttribute(trackIndexAttrN ame());
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.
412 disableShowingTextTracks();
413 if (trackIndex != trackIndexOffValue) {
414 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.
415 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
416 }
417
418 mediaControls().toggleTextTrackList();
419 event->setDefaultHandled();
420 }
421 MediaControlDivElement::defaultEventHandler(event);
422 }
423
424 void MediaControlTextTrackListElement::changeVisibility(bool isHidden)
425 {
426 if (isHidden) {
427 setIsWanted(true);
428 refreshTextTrackListMenu();
429 } else {
430 setIsWanted(false);
431 }
432 }
433
434 void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned indexToEnab le)
435 {
436 TextTrackList* trackList = mediaElement().textTracks();
437 if (trackList->length() == 0)
philipj_slow 2016/03/01 13:01:16 TextTrackList::anonymousIndexedGetter already hand
srivats 2016/03/30 00:46:43 Done.
438 return;
439 if (indexToEnable >= trackList->length())
440 return;
441 TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable);
442 if (track->canBeRendered())
443 track->setMode(TextTrack::showingKeyword());
444 }
445
446 void MediaControlTextTrackListElement::disableShowingTextTracks()
447 {
448 TextTrackList* trackList = mediaElement().textTracks();
449 for (unsigned i = 0; i < trackList->length(); ++i) {
450 TextTrack* track = trackList->anonymousIndexedGetter(i);
451 if (track->mode() == TextTrack::showingKeyword())
452 track->setMode(TextTrack::disabledKeyword());
453 }
454 }
455
456 String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track)
457 {
458 if (!track)
459 return mediaElement().locale().queryString(WebLocalizedString::TextTrack sOff);
460
461 String trackLabel = track->label();
462
463 if (trackLabel.isEmpty())
464 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
465
466 if (trackLabel.isEmpty())
467 trackLabel = String(mediaElement().locale().queryString(WebLocalizedStri ng::TextTracksNoLabel));
468
469 return trackLabel;
470 }
471
472 // TextTrack parameter when passed in as a nullptr, creates the "Off" list item in the track list.
473 PassRefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrac kListItem(TextTrack* track)
474 {
475 Document& document = this->document();
476 int trackIndex = track ? track->trackIndex() : trackIndexOffValue;
477 RefPtrWillBeRawPtr<HTMLLabelElement> trackItem = HTMLLabelElement::create(do cument, 0);
philipj_slow 2016/03/01 13:01:16 s/0/nullptr/
srivats 2016/03/30 00:46:43 Done.
478 trackItem->setShadowPseudoId(AtomicString("-internal-media-controls-text-tra ck-list-item",
479 AtomicString::ConstructFromLiteral));
480 RefPtrWillBeRawPtr<HTMLInputElement> trackItemInput = HTMLInputElement::crea te(document, 0, false);
philipj_slow 2016/03/01 13:01:16 s/0/nullptr/
srivats 2016/03/30 00:46:43 Done.
481 trackItemInput->setShadowPseudoId(AtomicString("-internal-media-controls-tex t-track-list-item-input",
482 AtomicString::ConstructFromLiteral));
483 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
484 trackItemInput->setIntegralAttribute(trackIndexAttrName(), trackIndex);
485 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
486 if (!track)
487 trackItemInput->setChecked(true);
488 } else {
489 // If there are multiple text tracks set to showing, they must all have
490 // checkmarks displayed.
491 if (track && track->mode() == TextTrack::showingKeyword())
492 trackItemInput->setChecked(true);
493 }
494 RefPtrWillBeRawPtr<HTMLSpanElement> trackKindMarker = HTMLSpanElement::creat e(document);
495 if (track && track->kind() == track->captionsKeyword()) {
496 trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-control s-text-track-list-kind-captions",
497 AtomicString::ConstructFromLiteral));
498 } 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.
499 trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-control s-text-track-list-kind-subtitles",
500 AtomicString::ConstructFromLiteral));
501 }
502 trackItem->appendChild(trackItemInput);
503 trackItem->appendChild(Text::create(document, getTextTrackLabel(track)));
504 trackItem->appendChild(trackKindMarker);
505 return trackItem;
506 }
507
508 void MediaControlTextTrackListElement::refreshTextTrackListMenu()
509 {
510 if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreRead y())
511 return;
512
513 removeChildren(OmitSubtreeModifiedEvent);
514
515 // Construct a menu for subtitles and captions
516 RefPtrWillBeRawPtr<HTMLDivElement> tracksSection = HTMLDivElement::create(th is->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
517 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
518 // Pass in a nullptr to createTextTrackListItem to create the "Off" track it em.
519 tracksSection->appendChild(createTextTrackListItem(nullptr));
520
521 TextTrackList* trackList = mediaElement().textTracks();
522 for (unsigned i = 0; i < trackList->length(); i++) {
523 TextTrack* track = trackList->anonymousIndexedGetter(i);
524 if (!track->canBeRendered())
525 continue;
526 tracksSection->appendChild(createTextTrackListItem(track));
527 }
528 appendChild(tracksSection);
529 }
530
531 // ----------------------------
532
373 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols) 533 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols)
374 : MediaControlInputElement(mediaControls, MediaSlider) 534 : MediaControlInputElement(mediaControls, MediaSlider)
375 { 535 {
376 } 536 }
377 537
378 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls) 538 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls)
379 { 539 {
380 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls)); 540 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls));
381 timeline->ensureUserAgentShadowRoot(); 541 timeline->ensureUserAgentShadowRoot();
382 timeline->setType(InputTypeNames::range); 542 timeline->setType(InputTypeNames::range);
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 } 809 }
650 810
651 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls) 811 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls)
652 { 812 {
653 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); 813 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls));
654 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral)); 814 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral));
655 return element.release(); 815 return element.release();
656 } 816 }
657 817
658 } // namespace blink 818 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698