12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/time/time.h" 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/frame_messages.h" 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/common/view_message_enums.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/test/render_view_test.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/accessibility/renderer_accessibility_complete.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/renderer/render_frame_impl.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/render_view_impl.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebSize.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/WebKit/public/web/WebAXObject.h" 167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h" 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/accessibility/ax_node_data.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebAXObject; 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDocument; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestRendererAccessibilityComplete : public RendererAccessibilityComplete { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch explicit TestRendererAccessibilityComplete(RenderFrameImpl* render_frame) 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : RendererAccessibilityComplete(render_frame) { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void SendPendingAccessibilityEvents() { 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RendererAccessibilityComplete::SendPendingAccessibilityEvents(); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RendererAccessibilityTest : public RenderViewTest { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RendererAccessibilityTest() {} 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewImpl* view() { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<RenderViewImpl*>(view_); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RenderFrameImpl* frame() { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame()); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetUp() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewTest::SetUp(); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_ = &render_thread_->sink(); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void SetMode(AccessibilityMode mode) { 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame()->OnSetAccessibilityMode(mode); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void GetLastAccEvent( 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams* params) { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const IPC::Message* message = 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(message); 6229b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch Tuple2<std::vector<AccessibilityHostMsg_EventParams>, int> param; 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_Events::Read(message, ¶m); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_GE(param.a.size(), 1U); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *params = param.a[0]; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int CountAccessibilityNodesSentToBrowser() { 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return event.update.nodes.size(); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC::TestSink* sink_; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityTest); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is not a test of true web accessibility, it's a test of 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a mode used on Windows 8 in Metro mode where an extremely simplified 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // accessibility tree containing only the current focused node is 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // generated. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetMode(AccessibilityModeEditableTextOnly); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set a minimum size and give focus so simulated events work. 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) view()->webwidget()->resize(blink::WebSize(500, 500)); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view()->webwidget()->setFocus(true); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string html = 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "<body>" 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <input>" 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <textarea></textarea>" 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <p contentEditable>Editable</p>" 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div tabindex=0 role=textbox>Textbox</div>" 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <button>Button</button>" 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <a href=#>Link</a>" 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "</body>"; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Load the test page. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should have sent a message to the browser with the initial focus 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // on the document. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("Initial focus on document"); 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.event_type, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_LAYOUT_COMPLETE); 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 1); 114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes.size(), 2U); 115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].id, 1); 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].role, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_ROLE_ROOT_WEB_AREA); 118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].state, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_READ_ONLY) | 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED)); 122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now focus the input element, and check everything again. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("input"); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('input').focus();"); 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.event_type, 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_FOCUS); 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 3); 135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].id, 1); 136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].role, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_ROLE_ROOT_WEB_AREA); 138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].state, 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_READ_ONLY) | 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE)); 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U); 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].id, 3); 143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].role, 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_ROLE_GROUP); 145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED)); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check other editable text nodes. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("textarea"); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('textarea').focus();"); 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 4); 158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED)); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("contentEditable"); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('p').focus();"); 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 5); 170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED)); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("role=textarea"); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('div').focus();"); 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 6); 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED)); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Try focusing things that aren't editable text. 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("button"); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('button').focus();"); 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 7); 195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED) | 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_READ_ONLY)); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("link"); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.querySelector('a').focus();"); 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 8); 208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(event.update.nodes[1].state, 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSABLE) | 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_FOCUSED) | 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (1U << ui::AX_STATE_READ_ONLY)); 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clear focus. 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE("Back to document."); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.activeElement.blur()"); 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EXPECT_EQ(event.id, 1); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The job of RendererAccessibilityComplete is to serialize the 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // accessibility tree built by WebKit and send it to the browser. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When the accessibility tree changes, it tries to send only 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the nodes that actually changed or were reparented. This test 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ensures that the messages sent are correct in cases when a page 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // reloads, and that internal state is properly garbage-collected. 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string html = 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "<body>" 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='A'>" 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='A1'></div>" 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='A2'></div>" 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "</body>"; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creating a RendererAccessibilityComplete should sent the tree 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the browser. 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TestRendererAccessibilityComplete> accessibility( 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If we post another event but the tree doesn't change, 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we should only send 1 node to the browser. 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebDocument document = view()->GetWebView()->mainFrame()->document(); 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_obj, 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_LAYOUT_COMPLETE); 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1, CountAccessibilityNodesSentToBrowser()); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure it's the root object that was updated. 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(root_obj.axID(), event.update.nodes[0].id); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If we reload the page and send a event, we should send 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // all 4 nodes to the browser. Also double-check that we didn't 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // leak any of the old BrowserTreeNodes. 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) document = view()->GetWebView()->mainFrame()->document(); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_obj = document.accessibilityObject(); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_obj, 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_LAYOUT_COMPLETE); 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Even if the first event is sent on an element other than 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the root, the whole tree should be updated because we know 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the browser doesn't have the root element. 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) document = view()->GetWebView()->mainFrame()->document(); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_obj = document.accessibilityObject(); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const WebAXObject& first_child = root_obj.childAt(0); 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) first_child, 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_LIVE_REGION_CHANGED); 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/253537 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \ 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DISABLED_AccessibilityMessagesQueueWhileSwappedOut 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#else 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \ 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AccessibilityMessagesQueueWhileSwappedOut 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RendererAccessibilityTest, 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MAYBE_AccessibilityMessagesQueueWhileSwappedOut) { 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string html = 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "<body>" 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch " <p>Hello, world.</p>" 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "</body>"; 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LoadHTML(html.c_str()); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static const int kProxyRoutingId = 13; 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Creating a RendererAccessibilityComplete should send the tree 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // to the browser. 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<TestRendererAccessibilityComplete> accessibility( 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 3160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser()); 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Post a "value changed" event, but then swap out 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // before sending it. It shouldn't send the event while 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // swapped out. 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sink_->ClearMessages(); 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebDocument document = view()->GetWebView()->mainFrame()->document(); 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch root_obj, 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_VALUE_CHANGED); 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId); 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(sink_->GetUniqueMessageMatching( 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_Events::ID)); 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Navigate, so we're not swapped out anymore. Now we should 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // send accessibility events again. Note that the 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // message that was queued up before will be quickly discarded 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // because the element it was referring to no longer exists, 33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // so the event here is from loading this new page. 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FrameMsg_Navigate_Params nav_params; 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nav_params.url = GURL("data:text/html,<p>Hello, again.</p>"); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nav_params.transition = ui::PAGE_TRANSITION_TYPED; 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nav_params.current_history_list_length = 1; 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nav_params.current_history_list_offset = 0; 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nav_params.pending_history_list_offset = 1; 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch nav_params.page_id = -1; 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nav_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1); 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame()->OnNavigate(nav_params); 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(sink_->GetUniqueMessageMatching( 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_Events::ID)); 350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RendererAccessibilityTest, HideAccessibilityObject) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test RendererAccessibilityComplete and make sure it sends the 35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // proper event to the browser when an object in the tree 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is hidden, but its children are not. 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string html = 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "<body>" 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='A'>" 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='B'>" 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='C' style='visibility:visible'>" 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "</body>"; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TestRendererAccessibilityComplete> accessibility( 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebDocument document = view()->GetWebView()->mainFrame()->document(); 37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject node_a = root_obj.childAt(0); 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject node_b = node_a.childAt(0); 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject node_c = node_b.childAt(0); 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Hide node 'B' ('C' stays visible). 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript( 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "document.getElementById('B').style.visibility = 'hidden';"); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Force layout now. 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.getElementById('B').offsetLeft;"); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send a childrenChanged on 'A'. 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node_a, 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_CHILDREN_CHANGED); 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 393c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_EQ(2U, event.update.nodes.size()); 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // RendererAccessibilityComplete notices that 'C' is being reparented, 396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // so it clears the subtree rooted at 'A', then updates 'A' and then 'C'. 397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear); 398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_a.axID(), event.update.nodes[0].id); 399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_c.axID(), event.update.nodes[1].id); 400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(2, CountAccessibilityNodesSentToBrowser()); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) { 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test RendererAccessibilityComplete and make sure it sends the 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // proper event to the browser when an object in the tree 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is shown, causing its own already-visible children to be 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // reparented to it. 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string html = 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "<body>" 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='A'>" 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='B' style='visibility:hidden'>" 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " <div role='group' id='C' style='visibility:visible'>" 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " </div>" 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "</body>"; 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadHTML(html.c_str()); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TestRendererAccessibilityComplete> accessibility( 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Show node 'B', then send a childrenChanged on 'A'. 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript( 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "document.getElementById('B').style.visibility = 'visible';"); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExecuteJavaScript("document.getElementById('B').offsetLeft;"); 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sink_->ClearMessages(); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebDocument document = view()->GetWebView()->mainFrame()->document(); 43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebAXObject node_a = root_obj.childAt(0); 433c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch WebAXObject node_b = node_a.childAt(0); 434c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch WebAXObject node_c = node_b.childAt(0); 435c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node_a, 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_CHILDREN_CHANGED); 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetLastAccEvent(&event); 443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_EQ(3U, event.update.nodes.size()); 445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear); 446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_a.axID(), event.update.nodes[0].id); 447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_b.axID(), event.update.nodes[1].id); 448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(node_c.axID(), event.update.nodes[2].id); 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) { 453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Test RendererAccessibilityComplete and make sure it sends the 454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // proper event to the browser when an object in the tree 455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // is detached, but its children are not. This can happen when 456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // a layout occurs and an anonymous render block is no longer needed. 457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string html = 458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "<body aria-label='Body'>" 459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "<span>1</span><span style='display:block'>2</span>" 460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "</body>"; 461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LoadHTML(html.c_str()); 462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<TestRendererAccessibilityComplete> accessibility( 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 4660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser()); 467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Initially, the accessibility tree looks like this: 469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Document 471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Body 472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Anonymous Block 473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Static Text "1" 4740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // +--Inline Text Box "1" 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Static Text "2" 4760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // +--Inline Text Box "2" 477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebDocument document = view()->GetWebView()->mainFrame()->document(); 478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebAXObject body = root_obj.childAt(0); 480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebAXObject anonymous_block = body.childAt(0); 481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebAXObject text_1 = anonymous_block.childAt(0); 482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebAXObject text_2 = body.childAt(1); 483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Change the display of the second 'span' back to inline, which causes the 485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // anonymous block to be destroyed. 486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ExecuteJavaScript( 487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "document.querySelectorAll('span')[1].style.display = 'inline';"); 488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Force layout now. 489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ExecuteJavaScript("document.body.offsetLeft;"); 490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Send a childrenChanged on the body. 492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sink_->ClearMessages(); 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accessibility->HandleAXEvent( 494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) body, 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::AX_EVENT_CHILDREN_CHANGED); 496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Afterwards, the accessibility tree looks like this: 500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Document 502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Body 503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Static Text "1" 5040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // +--Inline Text Box "1" 505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // +--Static Text "2" 5060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // +--Inline Text Box "2" 507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We just assert that there are now four nodes in the 509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // accessibility tree and that only three nodes needed 510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // to be updated (the body, the static text 1, and 511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the static text 2). 512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AccessibilityHostMsg_EventParams event; 514d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GetLastAccEvent(&event); 515c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_EQ(5U, event.update.nodes.size()); 516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 517c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(body.axID(), event.update.nodes[0].id); 518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(text_1.axID(), event.update.nodes[1].id); 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The third event is to update text_2, but its id changes 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // so we don't have a test expectation for it. 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RendererAccessibilityTest, EventOnObjectNotInTree) { 524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Test RendererAccessibilityComplete and make sure it doesn't send anything 525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // if we get a notification from Blink for an object that isn't in the 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // tree, like the scroll area that's the parent of the main document, 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // which we don't expose. 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string html = "<body><input></body>"; 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LoadHTML(html.c_str()); 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<TestRendererAccessibilityComplete> accessibility( 532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new TestRendererAccessibilityComplete(frame())); 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WebDocument document = view()->GetWebView()->mainFrame()->document(); 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WebAXObject root_obj = document.accessibilityObject(); 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WebAXObject scroll_area = root_obj.parentObject(); 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(blink::WebAXRoleScrollArea, scroll_area.role()); 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Try to fire a message on the scroll area, and assert that we just 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ignore it. 543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sink_->ClearMessages(); 544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accessibility->HandleAXEvent(scroll_area, 545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::AX_EVENT_VALUE_CHANGED); 546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) accessibility->SendPendingAccessibilityEvents(); 548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const IPC::Message* message = 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID); 551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(message); 55229b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch Tuple2<std::vector<AccessibilityHostMsg_EventParams>, int> param; 553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AccessibilityHostMsg_Events::Read(message, ¶m); 554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_EQ(0U, param.a.size()); 555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 558