OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |