15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector> 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/test/ash_test_base.h" 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/utf_string_conversions.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/ui/ash/accessibility/ax_tree_source_ash.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gtest/include/gtest/gtest.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/accessibility/ax_enums.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/accessibility/ax_node.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/accessibility/ax_serializable_tree.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/accessibility/ax_tree_serializer.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/accessibility/ax_tree_update.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/aura/window.h" 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/accessibility/ax_aura_obj_cache.h" 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/accessibility/ax_aura_obj_wrapper.h" 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/controls/textfield/textfield.h" 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/test/views_test_base.h" 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/widget/widget.h" 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing views::AXAuraObjCache; 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing views::AXAuraObjWrapper; 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing views::Textfield; 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing views::View; 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing views::Widget; 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Helper to count the number of nodes in a tree. 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t GetSize(AXAuraObjWrapper* tree) { 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t count = 1; 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<AXAuraObjWrapper*> out_children; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu tree->GetChildren(&out_children); 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < out_children.size(); ++i) 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu count += GetSize(out_children[i]); 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return count; 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class AXTreeSourceAshTest : public ash::test::AshTestBase { 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXTreeSourceAshTest() {} 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~AXTreeSourceAshTest() {} 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void SetUp() OVERRIDE { 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AshTestBase::SetUp(); 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu widget_ = new Widget(); 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Widget::InitParams init_params(Widget::InitParams::TYPE_POPUP); 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu init_params.parent = CurrentContext(); 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu widget_->Init(init_params); 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content_ = new View(); 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu widget_->SetContentsView(content_); 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu textfield_ = new Textfield(); 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu textfield_->SetText(base::ASCIIToUTF16("Value")); 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content_->AddChildView(textfield_); 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected: 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Widget* widget_; 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu View* content_; 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Textfield* textfield_; 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AXTreeSourceAshTest); 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(AXTreeSourceAshTest, Accessors) { 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXTreeSourceAsh ax_tree; 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(ax_tree.GetRoot()); 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // ID's should start at 1 and there should be a root. 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(1, ax_tree.GetRoot()->GetID()); 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Grab the content view directly from cache to avoid walking down the tree. 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjWrapper* content = 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjCache::GetInstance()->GetOrCreate(content_); 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<AXAuraObjWrapper*> content_children; 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ax_tree.GetChildren(content, &content_children); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(1U, content_children.size()); 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Walk down to the text field and assert it is what we expect. 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjWrapper* textfield = content_children[0]; 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjWrapper* cached_textfield = 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjCache::GetInstance()->GetOrCreate(textfield_); 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(cached_textfield, textfield); 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<AXAuraObjWrapper*> textfield_children; 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ax_tree.GetChildren(textfield, &textfield_children); 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(0U, textfield_children.size()); 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(content, textfield->GetParent()); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Try walking up the tree to the root. 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjWrapper* test_root = NULL; 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (AXAuraObjWrapper* root_finder = ax_tree.GetParent(content); root_finder; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_finder = ax_tree.GetParent(root_finder)) 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu test_root = root_finder; 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(ax_tree.GetRoot(), test_root); 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(AXTreeSourceAshTest, Serialization) { 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXTreeSourceAsh ax_tree; 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui::AXTreeSerializer<AXAuraObjWrapper*> ax_serializer(&ax_tree); 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui::AXTreeUpdate out_update; 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // This is the initial serialization. 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ax_serializer.SerializeChanges(ax_tree.GetRoot(), &out_update); 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // We should get an update per node. 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(GetSize(ax_tree.GetRoot()), out_update.nodes.size()); 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Try removing some child views and re-adding. 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content_->RemoveAllChildViews(false /* delete_children */); 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content_->AddChildView(textfield_); 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Grab the textfield since serialization only walks up the tree (not down 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // from root). 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjWrapper* textfield_wrapper = 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu AXAuraObjCache::GetInstance()->GetOrCreate(textfield_); 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Now, re-serialize. 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ui::AXTreeUpdate out_update2; 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ax_serializer.SerializeChanges(textfield_wrapper, &out_update2); 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // We should have far fewer updates this time around. 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(2U, out_update2.nodes.size()); 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(ui::AX_ROLE_CLIENT, 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu out_update2.nodes[0].role); 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(textfield_wrapper->GetID(), out_update2.nodes[1].id); 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(ui::AX_ROLE_TEXT_FIELD, 1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu out_update2.nodes[1].role); 1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(AXTreeSourceAshTest, DoDefault) { 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXTreeSourceAsh ax_tree; 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Grab a wrapper to |DoDefault| (click). 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXAuraObjWrapper* textfield_wrapper = 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXAuraObjCache::GetInstance()->GetOrCreate(textfield_); 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Click and verify focus. 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(textfield_->HasFocus()); 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) textfield_wrapper->DoDefault(); 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(textfield_->HasFocus()); 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(AXTreeSourceAshTest, Focus) { 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXTreeSourceAsh ax_tree; 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Grab a wrapper to focus. 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXAuraObjWrapper* textfield_wrapper = 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AXAuraObjCache::GetInstance()->GetOrCreate(textfield_); 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Focus and verify. 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(textfield_->HasFocus()); 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) textfield_wrapper->Focus(); 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(textfield_->HasFocus()); 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 164