Diff
Modified: trunk/LayoutTests/ChangeLog (222886 => 222887)
--- trunk/LayoutTests/ChangeLog 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/LayoutTests/ChangeLog 2017-10-04 23:43:13 UTC (rev 222887)
@@ -1,3 +1,14 @@
+2017-10-04 Nan Wang <n_w...@apple.com>
+
+ AX: Make video objects accessible on iOS
+ https://bugs.webkit.org/show_bug.cgi?id=177788
+ <rdar://problem/34778028>
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/ios-simulator/video-elements-ios-expected.txt: Added.
+ * accessibility/ios-simulator/video-elements-ios.html: Added.
+
2017-10-04 Wenson Hsieh <wenson_hs...@apple.com>
Add basic support for the version of DataTransferItemList.add that takes a File
Added: trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios-expected.txt (0 => 222887)
--- trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios-expected.txt 2017-10-04 23:43:13 UTC (rev 222887)
@@ -0,0 +1,20 @@
+
+This tests the video elements on iOS.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS video2 is null
+AXLabel: Video label, 9 seconds
+AXValue: 0 seconds
+PASS video.description is 'AXLabel: Video label, 9 seconds'
+PASS video.stringValue is 'AXValue: 0 seconds'
+PASS vid.paused is true
+PASS vid.paused is false
+PASS vid.paused is true
+PASS video.stringValue is 'AXValue: 2 seconds'
+PASS video.stringValue is 'AXValue: 1 seconds'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios.html (0 => 222887)
--- trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios.html (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/video-elements-ios.html 2017-10-04 23:43:13 UTC (rev 222887)
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body id="body">
+
+<video width="320" height="240" playsinline id="video" aria-label="Video label">
+ <source src="" type="video/mp4">
+ Your browser does not support the video tag.
+</video>
+
+<video width="320" height="240" controls id="video2" aria-label="Video label2">
+ <source src="" type="video/mp4">
+ Your browser does not support the video tag.
+</video>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This tests the video elements on iOS.");
+
+ if (window.accessibilityController) {
+ jsTestIsAsync = true;
+
+ var vid = document.getElementById("video");
+ var video = accessibilityController.accessibleElementById("video");
+
+ // We shouldn't expose video elements with native controls
+ var video2 = accessibilityController.accessibleElementById("video2");
+ shouldBeNull("video2");
+
+ vid._oncanplaythrough_ = function() {
+ debug(video.description);
+ debug(video.stringValue);
+ shouldBe("video.description", "'AXLabel: Video label, 9 seconds'");
+ shouldBe("video.stringValue", "'AXValue: 0 seconds'");
+
+ // Test play and pause.
+ shouldBeTrue("vid.paused");
+ video.press();
+ shouldBeFalse("vid.paused");
+ video.press();
+ shouldBeTrue("vid.paused");
+
+ // Test fast forward and rewind.
+ video.increment();
+ video.increment();
+ shouldBe("video.stringValue", "'AXValue: 2 seconds'");
+ video.decrement();
+ shouldBe("video.stringValue", "'AXValue: 1 seconds'");
+
+ finishJSTest();
+ };
+
+ }
+
+</script>
+
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (222886 => 222887)
--- trunk/Source/WebCore/ChangeLog 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/ChangeLog 2017-10-04 23:43:13 UTC (rev 222887)
@@ -1,3 +1,62 @@
+2017-10-04 Nan Wang <n_w...@apple.com>
+
+ AX: Make video objects accessible on iOS
+ https://bugs.webkit.org/show_bug.cgi?id=177788
+ <rdar://problem/34778028>
+
+ Reviewed by Chris Fleizach.
+
+ Exposed certain <video> elements on iOS:
+ 1. If they have no controls attribute set and have playsinline attribute set, that means
+ normally there are custom controls provided.
+ 2. Without autoplay attribute set. From iOS 10, with the motivation to improve performace by
+ replacing GIF with <video>, elements will now honor the autoplay attribute if they
+ have no audio. So normally those <video> elements are not interactive.
+
+ Also provided functions to let iOS users interact with the video elements:
+ - Play/Pause: accessibilityActivate
+ - Fast forward: accessibilityIncrement
+ - Rewind: accessibilityDecrement
+
+ Test: accessibility/ios-simulator/video-elements-ios.html
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::createFromRenderer):
+ * accessibility/AccessibilityMediaObject.cpp: Added.
+ (WebCore::AccessibilityMediaObject::AccessibilityMediaObject):
+ (WebCore::AccessibilityMediaObject::~AccessibilityMediaObject):
+ (WebCore::AccessibilityMediaObject::create):
+ (WebCore::AccessibilityMediaObject::computeAccessibilityIsIgnored const):
+ (WebCore::AccessibilityMediaObject::mediaElement const):
+ (WebCore::AccessibilityMediaObject::stringValue const):
+ (WebCore::AccessibilityMediaObject::interactiveVideoDuration const):
+ (WebCore::AccessibilityMediaObject::mediaSeek):
+ (WebCore::AccessibilityMediaObject::toggleMute):
+ (WebCore::AccessibilityMediaObject::increment):
+ (WebCore::AccessibilityMediaObject::decrement):
+ (WebCore::AccessibilityMediaObject::press):
+ (WebCore::AccessibilityMediaObject::hasControlsAttributeSet const):
+ (WebCore::AccessibilityMediaObject::isPlaying const):
+ (WebCore::AccessibilityMediaObject::isMuted const):
+ (WebCore::AccessibilityMediaObject::isAutoplayEnabled const):
+ (WebCore::AccessibilityMediaObject::isPlayingInline const):
+ (WebCore::AccessibilityMediaObject::enterFullscreen const):
+ * accessibility/AccessibilityMediaObject.h: Added.
+ * accessibility/AccessibilityObject.cpp:
+ * accessibility/AccessibilityObject.h:
+ (WebCore::AccessibilityObject::isMediaObject const):
+ * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+ (-[WebAccessibilityObjectWrapper accessibilityIsWebInteractiveVideo]):
+ (-[WebAccessibilityObjectWrapper interactiveVideoDescription]):
+ (-[WebAccessibilityObjectWrapper accessibilityIsMediaPlaying]):
+ (-[WebAccessibilityObjectWrapper accessibilityIsMediaMuted]):
+ (-[WebAccessibilityObjectWrapper accessibilityToggleMuteForMedia]):
+ (-[WebAccessibilityObjectWrapper accessibilityVideoEnterFullscreen]):
+ (-[WebAccessibilityObjectWrapper determineIsAccessibilityElement]):
+ (-[WebAccessibilityObjectWrapper stringValueShouldBeUsedInLabel]):
+ (-[WebAccessibilityObjectWrapper accessibilityLabel]):
+
2017-10-04 Wenson Hsieh <wenson_hs...@apple.com>
Add basic support for the version of DataTransferItemList.add that takes a File
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (222886 => 222887)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-10-04 23:43:13 UTC (rev 222887)
@@ -5012,6 +5012,7 @@
A91C9FBF1B6586DE00AFFD54 /* AccessibilityTree.h in Headers */ = {isa = PBXBuildFile; fileRef = A91C9FBD1B6586DE00AFFD54 /* AccessibilityTree.h */; };
A91C9FC21B659A6700AFFD54 /* AccessibilityTreeItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A91C9FC01B659A6700AFFD54 /* AccessibilityTreeItem.cpp */; };
A91C9FC31B659A6700AFFD54 /* AccessibilityTreeItem.h in Headers */ = {isa = PBXBuildFile; fileRef = A91C9FC11B659A6700AFFD54 /* AccessibilityTreeItem.h */; };
+ A9787CB41F5F5C6600C551C6 /* AccessibilityMediaObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9787CB31F5F5C6500C551C6 /* AccessibilityMediaObject.cpp */; };
A9C6E4E30D745E05006442E9 /* DOMMimeType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C6E4E10D745E05006442E9 /* DOMMimeType.cpp */; };
A9C6E4E40D745E05006442E9 /* DOMMimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C6E4E20D745E05006442E9 /* DOMMimeType.h */; };
A9C6E4E70D745E18006442E9 /* DOMMimeTypeArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C6E4E50D745E18006442E9 /* DOMMimeTypeArray.cpp */; };
@@ -13524,6 +13525,8 @@
A91C9FBD1B6586DE00AFFD54 /* AccessibilityTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityTree.h; sourceTree = "<group>"; };
A91C9FC01B659A6700AFFD54 /* AccessibilityTreeItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityTreeItem.cpp; sourceTree = "<group>"; };
A91C9FC11B659A6700AFFD54 /* AccessibilityTreeItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityTreeItem.h; sourceTree = "<group>"; };
+ A9787CB21F5F599200C551C6 /* AccessibilityMediaObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AccessibilityMediaObject.h; sourceTree = "<group>"; };
+ A9787CB31F5F5C6500C551C6 /* AccessibilityMediaObject.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityMediaObject.cpp; sourceTree = "<group>"; };
A9C6E4E10D745E05006442E9 /* DOMMimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DOMMimeType.cpp; sourceTree = "<group>"; };
A9C6E4E20D745E05006442E9 /* DOMMimeType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMMimeType.h; sourceTree = "<group>"; };
A9C6E4E50D745E18006442E9 /* DOMMimeTypeArray.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DOMMimeTypeArray.cpp; sourceTree = "<group>"; };
@@ -17697,6 +17700,8 @@
07B0ABCE1032242200FBDC33 /* AccessibilityMathMLElement.h */,
2981CAA4131822EC00D12F2A /* AccessibilityMediaControls.cpp */,
07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */,
+ A9787CB21F5F599200C551C6 /* AccessibilityMediaObject.h */,
+ A9787CB31F5F5C6500C551C6 /* AccessibilityMediaObject.cpp */,
76CDD2EC1103DA6600680521 /* AccessibilityMenuList.cpp */,
76CDD2ED1103DA6600680521 /* AccessibilityMenuList.h */,
76CDD2F01103DA6600680521 /* AccessibilityMenuListOption.cpp */,
@@ -31201,6 +31206,7 @@
29A812480FBB9CA900510293 /* AccessibilityObjectMac.mm in Sources */,
37F57AC31A50728F00876F98 /* AccessibilityProgressIndicator.cpp in Sources */,
37F57AC41A50729300876F98 /* AccessibilityRenderObject.cpp in Sources */,
+ A9787CB41F5F5C6600C551C6 /* AccessibilityMediaObject.cpp in Sources */,
37F57AC51A50729700876F98 /* AccessibilityScrollbar.cpp in Sources */,
37F57AC61A50729B00876F98 /* AccessibilityScrollView.cpp in Sources */,
37F57AC81A5072BC00876F98 /* AccessibilitySlider.cpp in Sources */,
Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (222886 => 222887)
--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2017-10-04 23:43:13 UTC (rev 222887)
@@ -43,6 +43,7 @@
#include "AccessibilityListBoxOption.h"
#include "AccessibilityMathMLElement.h"
#include "AccessibilityMediaControls.h"
+#include "AccessibilityMediaObject.h"
#include "AccessibilityMenuList.h"
#include "AccessibilityMenuListOption.h"
#include "AccessibilityMenuListPopup.h"
@@ -444,6 +445,11 @@
if (node && is<HTMLLabelElement>(node) && nodeHasRole(node, nullAtom()))
return AccessibilityLabel::create(renderer);
+#if PLATFORM(IOS)
+ if (is<HTMLMediaElement>(node) && nodeHasRole(node, nullAtom()))
+ return AccessibilityMediaObject::create(renderer);
+#endif
+
#if ENABLE(VIDEO)
// media controls
if (node && node->isMediaControlElement())
Added: trunk/Source/WebCore/accessibility/AccessibilityMediaObject.cpp (0 => 222887)
--- trunk/Source/WebCore/accessibility/AccessibilityMediaObject.cpp (rev 0)
+++ trunk/Source/WebCore/accessibility/AccessibilityMediaObject.cpp 2017-10-04 23:43:13 UTC (rev 222887)
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if PLATFORM(IOS)
+#include "AccessibilityMediaObject.h"
+
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "HTMLVideoElement.h"
+#include "LocalizedStrings.h"
+
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+AccessibilityMediaObject::AccessibilityMediaObject(RenderObject* renderer)
+ : AccessibilityRenderObject(renderer)
+{
+}
+
+AccessibilityMediaObject::~AccessibilityMediaObject()
+{
+}
+
+Ref<AccessibilityMediaObject> AccessibilityMediaObject::create(RenderObject* renderer)
+{
+ return adoptRef(*new AccessibilityMediaObject(renderer));
+}
+
+bool AccessibilityMediaObject::computeAccessibilityIsIgnored() const
+{
+ return accessibilityIsIgnoredByDefault();
+}
+
+HTMLMediaElement* AccessibilityMediaObject::mediaElement() const
+{
+ Node* node = this->node();
+ if (!is<HTMLMediaElement>(*node))
+ return nullptr;
+ return downcast<HTMLMediaElement>(node);
+}
+
+String AccessibilityMediaObject::stringValue() const
+{
+ if (HTMLMediaElement* element = mediaElement())
+ return localizedMediaTimeDescription(element->currentTime());
+ return AccessibilityRenderObject::stringValue();
+}
+
+String AccessibilityMediaObject::interactiveVideoDuration() const
+{
+ if (HTMLMediaElement* element = mediaElement())
+ return localizedMediaTimeDescription(element->duration());
+ return String();
+}
+
+void AccessibilityMediaObject::mediaSeek(AXSeekDirection direction)
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return;
+
+ // Step 5% each time.
+ const double seekStep = .05;
+ double current = element->currentTime();
+ double duration = element->duration();
+ double timeDelta = ceil(duration * seekStep);
+
+ double time = direction == AXSeekForward ? std::min(current + timeDelta, duration) : std::max(current - timeDelta, 0.0);
+ element->setCurrentTime(time);
+}
+
+void AccessibilityMediaObject::toggleMute()
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return;
+
+ element->setMuted(!element->muted());
+}
+
+void AccessibilityMediaObject::increment()
+{
+ mediaSeek(AXSeekForward);
+}
+
+void AccessibilityMediaObject::decrement()
+{
+ mediaSeek(AXSeekBackward);
+}
+
+bool AccessibilityMediaObject::press()
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ // We can safely call the internal togglePlayState method, which doesn't check restrictions,
+ // because this method is only called from user interaction.
+ element->togglePlayState();
+ return true;
+}
+
+bool AccessibilityMediaObject::hasControlsAttributeSet() const
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ return element->controls();
+}
+
+bool AccessibilityMediaObject::isPlaying() const
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ return element->isPlaying();
+}
+
+bool AccessibilityMediaObject::isMuted() const
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ return element->muted();
+}
+
+bool AccessibilityMediaObject::isAutoplayEnabled() const
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ return element->autoplay();
+}
+
+bool AccessibilityMediaObject::isPlayingInline() const
+{
+ HTMLMediaElement* element = mediaElement();
+ if (!element)
+ return false;
+
+ return !element->mediaSession().requiresFullscreenForVideoPlayback(*element);
+}
+
+void AccessibilityMediaObject::enterFullscreen() const
+{
+ Node* node = this->node();
+ if (!is<HTMLVideoElement>(node))
+ return;
+
+ HTMLVideoElement* element = downcast<HTMLVideoElement>(node);
+ element->enterFullscreen();
+}
+
+} // namespace WebCore
+
+#endif // PLATFORM(IOS)
Added: trunk/Source/WebCore/accessibility/AccessibilityMediaObject.h (0 => 222887)
--- trunk/Source/WebCore/accessibility/AccessibilityMediaObject.h (rev 0)
+++ trunk/Source/WebCore/accessibility/AccessibilityMediaObject.h 2017-10-04 23:43:13 UTC (rev 222887)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS)
+
+#include "AccessibilityRenderObject.h"
+
+namespace WebCore {
+
+class AccessibilityMediaObject final : public AccessibilityRenderObject {
+public:
+ static Ref<AccessibilityMediaObject> create(RenderObject*);
+ virtual ~AccessibilityMediaObject();
+
+ void enterFullscreen() const;
+ void toggleMute();
+
+ bool hasControlsAttributeSet() const;
+ String interactiveVideoDuration() const;
+ bool isPlaying() const;
+ bool isAutoplayEnabled() const;
+ bool isPlayingInline() const;
+ bool isMuted() const;
+
+private:
+ enum AXSeekDirection { AXSeekForward, AXSeekBackward };
+ explicit AccessibilityMediaObject(RenderObject*);
+ bool computeAccessibilityIsIgnored() const final;
+ bool isMediaObject() const final { return true; }
+
+ String stringValue() const override;
+ bool press() override;
+ void increment() override;
+ void decrement() override;
+
+ HTMLMediaElement* mediaElement() const;
+
+ void mediaSeek(AXSeekDirection);
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_ACCESSIBILITY(AccessibilityMediaObject, isMediaObject())
+#endif // PLATFORM(IOS)
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (222886 => 222887)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2017-10-04 23:43:13 UTC (rev 222887)
@@ -46,6 +46,7 @@
#include "HTMLDetailsElement.h"
#include "HTMLFormControlElement.h"
#include "HTMLInputElement.h"
+#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "HitTestResult.h"
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (222886 => 222887)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.h 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h 2017-10-04 23:43:13 UTC (rev 222887)
@@ -563,6 +563,7 @@
virtual bool isSpinButtonPart() const { return false; }
virtual bool isMockObject() const { return false; }
virtual bool isMediaControlLabel() const { return false; }
+ virtual bool isMediaObject() const { return false; }
bool isSwitch() const { return roleValue() == SwitchRole; }
bool isToggleButton() const { return roleValue() == ToggleButtonRole; }
bool isTextControl() const;
Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (222886 => 222887)
--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm 2017-10-04 23:27:45 UTC (rev 222886)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm 2017-10-04 23:43:13 UTC (rev 222887)
@@ -29,6 +29,7 @@
#if HAVE(ACCESSIBILITY) && PLATFORM(IOS)
#import "AccessibilityAttachment.h"
+#import "AccessibilityMediaObject.h"
#import "AccessibilityRenderObject.h"
#import "AccessibilityScrollView.h"
#import "AccessibilityTable.h"
@@ -665,6 +666,70 @@
return traits;
}
+- (BOOL)accessibilityIsWebInteractiveVideo
+{
+ if (![self _prepareAccessibilityCall])
+ return NO;
+
+ // Only make the video object interactive if it plays inline and has no native controls.
+ if (m_object->roleValue() != VideoRole || !is<AccessibilityMediaObject>(m_object))
+ return NO;
+
+ AccessibilityMediaObject* mediaObject = downcast<AccessibilityMediaObject>(m_object);
+ return !mediaObject->isAutoplayEnabled() && mediaObject->isPlayingInline() && !downcast<AccessibilityMediaObject>(m_object)->hasControlsAttributeSet();
+}
+
+- (NSString *)interactiveVideoDescription
+{
+ if (!is<AccessibilityMediaObject>(m_object))
+ return nil;
+ return downcast<AccessibilityMediaObject>(m_object)->interactiveVideoDuration();
+}
+
+- (BOOL)accessibilityIsMediaPlaying
+{
+ if (![self _prepareAccessibilityCall])
+ return NO;
+
+ if (!is<AccessibilityMediaObject>(m_object))
+ return NO;
+
+ return downcast<AccessibilityMediaObject>(m_object)->isPlaying();
+}
+
+- (BOOL)accessibilityIsMediaMuted
+{
+ if (![self _prepareAccessibilityCall])
+ return NO;
+
+ if (!is<AccessibilityMediaObject>(m_object))
+ return NO;
+
+ return downcast<AccessibilityMediaObject>(m_object)->isMuted();
+}
+
+- (void)accessibilityToggleMuteForMedia
+{
+ if (![self _prepareAccessibilityCall])
+ return;
+
+ if (!is<AccessibilityMediaObject>(m_object))
+ return;
+
+ downcast<AccessibilityMediaObject>(m_object)->toggleMute();
+}
+
+- (void)accessibilityVideoEnterFullscreen
+{
+ if (![self _prepareAccessibilityCall])
+ return;
+
+ if (!is<AccessibilityMediaObject>(m_object))
+ return;
+
+ downcast<AccessibilityMediaObject>(m_object)->enterFullscreen();
+}
+
- (uint64_t)_accessibilityTextEntryTraits
{
uint64_t traits = [self _axTextEntryTrait];
@@ -828,6 +893,9 @@
return true;
return false;
+ case VideoRole:
+ return [self accessibilityIsWebInteractiveVideo];
+
// Links can sometimes be elements (when they only contain static text or don't contain anything).
// They should not be elements when containing text and other types.
case WebCoreLinkRole:
@@ -944,7 +1012,6 @@
case ToolbarRole:
case UnknownRole:
case UserInterfaceTooltipRole:
- case VideoRole:
case WebApplicationRole:
case WebAreaRole:
case WindowRole:
@@ -975,6 +1042,8 @@
return NO;
if (m_object->isFileUploadButton())
return NO;
+ if ([self accessibilityIsWebInteractiveVideo])
+ return NO;
return YES;
}
@@ -1040,6 +1109,7 @@
NSString *axTitle = [self baseAccessibilityTitle];
NSString *axDescription = [self baseAccessibilityDescription];
NSString *landmarkDescription = [self ariaLandmarkRoleDescription];
+ NSString *interactiveVideoDescription = [self interactiveVideoDescription];
// We should expose the value of the input type date or time through AXValue instead of AXTitle.
if (m_object->isInputTypePopupButton() && [axTitle isEqualToString:[self accessibilityValue]])
@@ -1061,6 +1131,7 @@
appendStringToResult(result, valueLabel);
}
appendStringToResult(result, landmarkDescription);
+ appendStringToResult(result, interactiveVideoDescription);
return [result length] ? result : nil;
}