blob: 2a074451b5bf8bba402d638934bf901f0ca57a39 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "net/base/data_url.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
namespace content {
namespace {
class AccessibilityActionBrowserTest : public ContentBrowserTest {
public:
AccessibilityActionBrowserTest() {}
~AccessibilityActionBrowserTest() override {}
protected:
BrowserAccessibility* FindNode(ax::mojom::Role role,
const std::string& name) {
BrowserAccessibility* root = GetManager()->GetRoot();
CHECK(root);
return FindNodeInSubtree(*root, role, name);
}
BrowserAccessibilityManager* GetManager() {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
return web_contents->GetRootBrowserAccessibilityManager();
}
void GetBitmapFromImageDataURL(BrowserAccessibility* target,
SkBitmap* bitmap) {
std::string image_data_url =
target->GetStringAttribute(ax::mojom::StringAttribute::kImageDataUrl);
std::string mimetype;
std::string charset;
std::string png_data;
ASSERT_TRUE(net::DataURL::Parse(GURL(image_data_url),
&mimetype, &charset, &png_data));
ASSERT_EQ("image/png", mimetype);
ASSERT_TRUE(gfx::PNGCodec::Decode(
reinterpret_cast<const unsigned char*>(png_data.data()),
png_data.size(), bitmap));
}
private:
BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
ax::mojom::Role role,
const std::string& name) {
if (node.GetRole() == role &&
node.GetStringAttribute(ax::mojom::StringAttribute::kName) == name)
return &node;
for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
BrowserAccessibility* result = FindNodeInSubtree(
*node.PlatformGetChild(i), role, name);
if (result)
return result;
}
return nullptr;
}
};
} // namespace
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, FocusAction) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url("data:text/html,"
"<button>One</button>"
"<button>Two</button>"
"<button>Three</button>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target = FindNode(ax::mojom::Role::kButton, "One");
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(
shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
GetManager()->SetFocus(*target);
waiter2.WaitForNotification();
BrowserAccessibility* focus = GetManager()->GetFocus();
EXPECT_EQ(focus->GetId(), target->GetId());
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
IncrementDecrementActions) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url("data:text/html,"
"<input type=range min=2 value=8 max=10 step=2>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target = FindNode(ax::mojom::Role::kSlider, "");
ASSERT_NE(nullptr, target);
EXPECT_EQ(8.0, target->GetFloatAttribute(
ax::mojom::FloatAttribute::kValueForRange));
// Increment, should result in value changing from 8 to 10.
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kValueChanged);
GetManager()->Increment(*target);
waiter2.WaitForNotification();
}
EXPECT_EQ(10.0, target->GetFloatAttribute(
ax::mojom::FloatAttribute::kValueForRange));
// Increment, should result in value staying the same (max).
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kValueChanged);
GetManager()->Increment(*target);
waiter2.WaitForNotification();
}
EXPECT_EQ(10.0, target->GetFloatAttribute(
ax::mojom::FloatAttribute::kValueForRange));
// Decrement, should result in value changing from 10 to 8.
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kValueChanged);
GetManager()->Decrement(*target);
waiter2.WaitForNotification();
}
EXPECT_EQ(8.0, target->GetFloatAttribute(
ax::mojom::FloatAttribute::kValueForRange));
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, Scroll) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url(
"data:text/html,"
"<div style='width:100; height:50; overflow:scroll' "
"aria-label='shakespeare'>"
"To be or not to be, that is the question."
"</div>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target =
FindNode(ax::mojom::Role::kGenericContainer, "shakespeare");
EXPECT_NE(target, nullptr);
int y_before = target->GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
AccessibilityNotificationWaiter waiter2(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kScrollPositionChanged);
ui::AXActionData data;
data.action = ax::mojom::Action::kScrollDown;
data.target_node_id = target->GetId();
target->manager()->delegate()->AccessibilityPerformAction(data);
waiter2.WaitForNotification();
int y_after = target->GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
EXPECT_GT(y_after, y_before);
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url("data:text/html,"
"<body>"
"<canvas aria-label='canvas' id='c' width='4' height='2'></canvas>"
"<script>\n"
" var c = document.getElementById('c').getContext('2d');\n"
" c.beginPath();\n"
" c.moveTo(0, 0.5);\n"
" c.lineTo(4, 0.5);\n"
" c.strokeStyle = '%23ff0000';\n"
" c.stroke();\n"
" c.beginPath();\n"
" c.moveTo(0, 1.5);\n"
" c.lineTo(4, 1.5);\n"
" c.strokeStyle = '%230000ff';\n"
" c.stroke();\n"
"</script>"
"</body>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target = FindNode(ax::mojom::Role::kCanvas, "canvas");
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kImageFrameUpdated);
GetManager()->GetImageData(*target, gfx::Size());
waiter2.WaitForNotification();
SkBitmap bitmap;
GetBitmapFromImageDataURL(target, &bitmap);
ASSERT_EQ(4, bitmap.width());
ASSERT_EQ(2, bitmap.height());
EXPECT_EQ(SK_ColorRED, bitmap.getColor(0, 0));
EXPECT_EQ(SK_ColorRED, bitmap.getColor(1, 0));
EXPECT_EQ(SK_ColorRED, bitmap.getColor(2, 0));
EXPECT_EQ(SK_ColorRED, bitmap.getColor(3, 0));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 1));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(1, 1));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(2, 1));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(3, 1));
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImageScale) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url("data:text/html,"
"<body>"
"<canvas aria-label='canvas' id='c' width='40' height='20'></canvas>"
"<script>\n"
" var c = document.getElementById('c').getContext('2d');\n"
" c.fillStyle = '%2300ff00';\n"
" c.fillRect(0, 0, 40, 10);\n"
" c.fillStyle = '%23ff00ff';\n"
" c.fillRect(0, 10, 40, 10);\n"
"</script>"
"</body>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target = FindNode(ax::mojom::Role::kCanvas, "canvas");
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kImageFrameUpdated);
GetManager()->GetImageData(*target, gfx::Size(4, 4));
waiter2.WaitForNotification();
SkBitmap bitmap;
GetBitmapFromImageDataURL(target, &bitmap);
ASSERT_EQ(4, bitmap.width());
ASSERT_EQ(2, bitmap.height());
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0));
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(1, 0));
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(2, 0));
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(3, 0));
EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, 1));
EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(1, 1));
EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(2, 1));
EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(3, 1));
}
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, ImgElementGetImage) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url("data:text/html,"
"<body>"
"<img src='data:image/gif;base64,R0lGODdhAgADAKEDAAAA//"
"8AAAD/AP///ywAAAAAAgADAAACBEwkAAUAOw=='>"
"</body>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
BrowserAccessibility* target = FindNode(ax::mojom::Role::kImage, "");
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kImageFrameUpdated);
GetManager()->GetImageData(*target, gfx::Size());
waiter2.WaitForNotification();
SkBitmap bitmap;
GetBitmapFromImageDataURL(target, &bitmap);
ASSERT_EQ(2, bitmap.width());
ASSERT_EQ(3, bitmap.height());
EXPECT_EQ(SK_ColorRED, bitmap.getColor(0, 0));
EXPECT_EQ(SK_ColorRED, bitmap.getColor(1, 0));
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 1));
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(1, 1));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 2));
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(1, 2));
}
} // namespace content