diff --git a/accessible/android/AccessibleWrap.cpp b/accessible/android/AccessibleWrap.cpp index 3e3c07b3f6e6..ccb7761333b2 100644 --- a/accessible/android/AccessibleWrap.cpp +++ b/accessible/android/AccessibleWrap.cpp @@ -206,154 +206,6 @@ AccessibleWrap::GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) { return false; } -mozilla::java::GeckoBundle::LocalRef -AccessibleWrap::CreateBundle(int32_t aParentID, - role aRole, - uint64_t aState, - const nsString& aName, - const nsString& aTextValue, - const nsString& aDOMNodeID, - const nsIntRect& aBounds, - double aCurVal, - double aMinVal, - double aMaxVal, - double aStep, - nsIPersistentProperties* aAttributes, - const nsTArray& aChildren) const -{ - GECKOBUNDLE_START(nodeInfo); - GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID())); - GECKOBUNDLE_PUT(nodeInfo, "parentId", java::sdk::Integer::ValueOf(aParentID)); - uint64_t flags = GetFlags(aRole, aState); - GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags)); - - nsAutoString geckoRole; - nsAutoString roleDescription; - int32_t androidClass = java::SessionAccessibility::CLASSNAME_VIEW; - if (VirtualViewID() == kNoID) { - androidClass = java::SessionAccessibility::CLASSNAME_WEBVIEW; - } else { - GetRoleDescription(aRole, geckoRole, roleDescription); - androidClass = GetAndroidClass(aRole); - } - - GECKOBUNDLE_PUT( - nodeInfo, "roleDescription", jni::StringParam(roleDescription)); - GECKOBUNDLE_PUT(nodeInfo, "geckoRole", jni::StringParam(geckoRole)); - GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(androidClass)); - - if (!aTextValue.IsEmpty() && - (flags & java::SessionAccessibility::FLAG_EDITABLE)) { - GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(aName)); - GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aTextValue)); - } else { - GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aName)); - } - - if (!aDOMNodeID.IsEmpty()) { - GECKOBUNDLE_PUT( - nodeInfo, "viewIdResourceName", jni::StringParam(aDOMNodeID)); - } - - const int32_t data[4] = { - aBounds.x, aBounds.y, aBounds.x + aBounds.width, aBounds.y + aBounds.height - }; - GECKOBUNDLE_PUT(nodeInfo, "bounds", jni::IntArray::New(data, 4)); - - if (HasNumericValue()) { - GECKOBUNDLE_START(rangeInfo); - if (aMaxVal == 1 && aMinVal == 0) { - GECKOBUNDLE_PUT( - rangeInfo, "type", java::sdk::Integer::ValueOf(2)); // percent - } else if (std::round(aStep) != aStep) { - GECKOBUNDLE_PUT( - rangeInfo, "type", java::sdk::Integer::ValueOf(1)); // float - } else { - GECKOBUNDLE_PUT( - rangeInfo, "type", java::sdk::Integer::ValueOf(0)); // integer - } - - if (!IsNaN(aCurVal)) { - GECKOBUNDLE_PUT(rangeInfo, "current", java::sdk::Double::New(aCurVal)); - } - if (!IsNaN(aMinVal)) { - GECKOBUNDLE_PUT(rangeInfo, "min", java::sdk::Double::New(aMinVal)); - } - if (!IsNaN(aMaxVal)) { - GECKOBUNDLE_PUT(rangeInfo, "max", java::sdk::Double::New(aMaxVal)); - } - - GECKOBUNDLE_FINISH(rangeInfo); - GECKOBUNDLE_PUT(nodeInfo, "rangeInfo", rangeInfo); - } - - nsString inputTypeAttr; - nsAccUtils::GetAccAttr(aAttributes, nsGkAtoms::textInputType, inputTypeAttr); - int32_t inputType = GetInputType(inputTypeAttr); - if (inputType) { - GECKOBUNDLE_PUT(nodeInfo, "inputType", java::sdk::Integer::ValueOf(inputType)); - } - - nsString posinset; - nsresult rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("posinset"), posinset); - if (NS_SUCCEEDED(rv)) { - int32_t rowIndex; - if (sscanf(NS_ConvertUTF16toUTF8(posinset).get(), "%d", &rowIndex) > 0) { - GECKOBUNDLE_START(collectionItemInfo); - GECKOBUNDLE_PUT( - collectionItemInfo, "rowIndex", java::sdk::Integer::ValueOf(rowIndex)); - GECKOBUNDLE_PUT( - collectionItemInfo, "columnIndex", java::sdk::Integer::ValueOf(0)); - GECKOBUNDLE_PUT( - collectionItemInfo, "rowSpan", java::sdk::Integer::ValueOf(1)); - GECKOBUNDLE_PUT( - collectionItemInfo, "columnSpan", java::sdk::Integer::ValueOf(1)); - GECKOBUNDLE_FINISH(collectionItemInfo); - - GECKOBUNDLE_PUT(nodeInfo, "collectionItemInfo", collectionItemInfo); - } - } - - nsString colSize; - rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("child-item-count"), - colSize); - if (NS_SUCCEEDED(rv)) { - int32_t rowCount; - if (sscanf(NS_ConvertUTF16toUTF8(colSize).get(), "%d", &rowCount) > 0) { - GECKOBUNDLE_START(collectionInfo); - GECKOBUNDLE_PUT( - collectionInfo, "rowCount", java::sdk::Integer::ValueOf(rowCount)); - GECKOBUNDLE_PUT( - collectionInfo, "columnCount", java::sdk::Integer::ValueOf(1)); - - nsString unused; - rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("hierarchical"), - unused); - if (NS_SUCCEEDED(rv)) { - GECKOBUNDLE_PUT( - collectionInfo, "isHierarchical", java::sdk::Boolean::TRUE()); - } - - if (IsSelect()) { - int32_t selectionMode = (aState & states::MULTISELECTABLE) ? 2 : 1; - GECKOBUNDLE_PUT(collectionInfo, - "selectionMode", - java::sdk::Integer::ValueOf(selectionMode)); - } - GECKOBUNDLE_FINISH(collectionInfo); - - GECKOBUNDLE_PUT(nodeInfo, "collectionInfo", collectionInfo); - } - } - - GECKOBUNDLE_PUT(nodeInfo, - "children", - jni::IntArray::New(aChildren.Elements(), aChildren.Length())); - GECKOBUNDLE_FINISH(nodeInfo); - - return nodeInfo; -} - uint64_t AccessibleWrap::GetFlags(role aRole, uint64_t aState) { @@ -495,7 +347,7 @@ AccessibleWrap::GetInputType(const nsString& aInputTypeAttr) } void -AccessibleWrap::DOMNodeID(nsString& aDOMNodeID) +AccessibleWrap::WrapperDOMNodeID(nsString& aDOMNodeID) { if (mContent) { nsAtom* id = mContent->GetID(); @@ -505,25 +357,170 @@ AccessibleWrap::DOMNodeID(nsString& aDOMNodeID) } } +bool +AccessibleWrap::WrapperRangeInfo(double* aCurVal, double* aMinVal, + double* aMaxVal, double* aStep) +{ + if (HasNumericValue()) { + *aCurVal = CurValue(); + *aMinVal = MinValue(); + *aMaxVal = MaxValue(); + *aStep = Step(); + return true; + } + + return false; +} + mozilla::java::GeckoBundle::LocalRef AccessibleWrap::ToBundle() { - if (IsDefunct()) { + if (!IsProxy() && IsDefunct()) { return nullptr; } - AccessibleWrap* parent = static_cast(Parent()); - nsAutoString name; - Name(name); + GECKOBUNDLE_START(nodeInfo); + GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID())); - nsAutoString value; - Value(value); + AccessibleWrap* parent = WrapperParent(); + GECKOBUNDLE_PUT(nodeInfo, "parentId", + java::sdk::Integer::ValueOf(parent ? parent->VirtualViewID() : 0)); + + role role = WrapperRole(); + uint64_t state = State(); + uint64_t flags = GetFlags(role, state); + GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags)); + + nsAutoString geckoRole; + nsAutoString roleDescription; + if (VirtualViewID() != kNoID) { + GetRoleDescription(role, geckoRole, roleDescription); + } + + GECKOBUNDLE_PUT( + nodeInfo, "roleDescription", jni::StringParam(roleDescription)); + GECKOBUNDLE_PUT(nodeInfo, "geckoRole", jni::StringParam(geckoRole)); + GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(AndroidClass())); + + nsAutoString text; + if (state & states::EDITABLE) { + Value(text); + } + + if (!text.IsEmpty()) { + nsAutoString hint; + Name(hint); + GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(hint)); + } else { + Name(text); + } + GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(text)); nsAutoString viewIdResourceName; - DOMNodeID(viewIdResourceName); + WrapperDOMNodeID(viewIdResourceName); + if (!viewIdResourceName.IsEmpty()) { + GECKOBUNDLE_PUT( + nodeInfo, "viewIdResourceName", jni::StringParam(viewIdResourceName)); + } + + nsIntRect bounds = Bounds(); + const int32_t data[4] = { + bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height + }; + GECKOBUNDLE_PUT(nodeInfo, "bounds", jni::IntArray::New(data, 4)); + + double curValue = 0; + double minValue = 0; + double maxValue = 0; + double step = 0; + if (WrapperRangeInfo(&curValue, &minValue, &maxValue, &step)) { + GECKOBUNDLE_START(rangeInfo); + if (maxValue == 1 && minValue == 0) { + GECKOBUNDLE_PUT( + rangeInfo, "type", java::sdk::Integer::ValueOf(2)); // percent + } else if (std::round(step) != step) { + GECKOBUNDLE_PUT( + rangeInfo, "type", java::sdk::Integer::ValueOf(1)); // float + } else { + GECKOBUNDLE_PUT( + rangeInfo, "type", java::sdk::Integer::ValueOf(0)); // integer + } + + if (!IsNaN(curValue)) { + GECKOBUNDLE_PUT(rangeInfo, "current", java::sdk::Double::New(curValue)); + } + if (!IsNaN(minValue)) { + GECKOBUNDLE_PUT(rangeInfo, "min", java::sdk::Double::New(minValue)); + } + if (!IsNaN(maxValue)) { + GECKOBUNDLE_PUT(rangeInfo, "max", java::sdk::Double::New(maxValue)); + } + + GECKOBUNDLE_FINISH(rangeInfo); + GECKOBUNDLE_PUT(nodeInfo, "rangeInfo", rangeInfo); + } nsCOMPtr attributes = Attributes(); + nsString inputTypeAttr; + nsAccUtils::GetAccAttr(attributes, nsGkAtoms::textInputType, inputTypeAttr); + int32_t inputType = GetInputType(inputTypeAttr); + if (inputType) { + GECKOBUNDLE_PUT(nodeInfo, "inputType", java::sdk::Integer::ValueOf(inputType)); + } + + nsString posinset; + nsresult rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("posinset"), posinset); + if (NS_SUCCEEDED(rv)) { + int32_t rowIndex; + if (sscanf(NS_ConvertUTF16toUTF8(posinset).get(), "%d", &rowIndex) > 0) { + GECKOBUNDLE_START(collectionItemInfo); + GECKOBUNDLE_PUT( + collectionItemInfo, "rowIndex", java::sdk::Integer::ValueOf(rowIndex)); + GECKOBUNDLE_PUT( + collectionItemInfo, "columnIndex", java::sdk::Integer::ValueOf(0)); + GECKOBUNDLE_PUT( + collectionItemInfo, "rowSpan", java::sdk::Integer::ValueOf(1)); + GECKOBUNDLE_PUT( + collectionItemInfo, "columnSpan", java::sdk::Integer::ValueOf(1)); + GECKOBUNDLE_FINISH(collectionItemInfo); + + GECKOBUNDLE_PUT(nodeInfo, "collectionItemInfo", collectionItemInfo); + } + } + + nsString colSize; + rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("child-item-count"), + colSize); + if (NS_SUCCEEDED(rv)) { + int32_t rowCount; + if (sscanf(NS_ConvertUTF16toUTF8(colSize).get(), "%d", &rowCount) > 0) { + GECKOBUNDLE_START(collectionInfo); + GECKOBUNDLE_PUT( + collectionInfo, "rowCount", java::sdk::Integer::ValueOf(rowCount)); + GECKOBUNDLE_PUT( + collectionInfo, "columnCount", java::sdk::Integer::ValueOf(1)); + + nsString unused; + rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("hierarchical"), + unused); + if (NS_SUCCEEDED(rv)) { + GECKOBUNDLE_PUT( + collectionInfo, "isHierarchical", java::sdk::Boolean::TRUE()); + } + + if (IsSelect()) { + int32_t selectionMode = (state & states::MULTISELECTABLE) ? 2 : 1; + GECKOBUNDLE_PUT(collectionInfo, + "selectionMode", + java::sdk::Integer::ValueOf(selectionMode)); + } + GECKOBUNDLE_FINISH(collectionInfo); + + GECKOBUNDLE_PUT(nodeInfo, "collectionInfo", collectionInfo); + } + } + auto childCount = ChildCount(); nsTArray children(childCount); for (uint32_t i = 0; i < childCount; i++) { @@ -531,17 +528,10 @@ AccessibleWrap::ToBundle() children.AppendElement(child->VirtualViewID()); } - return CreateBundle(parent ? parent->VirtualViewID() : 0, - Role(), - State(), - name, - value, - viewIdResourceName, - Bounds(), - CurValue(), - MinValue(), - MaxValue(), - Step(), - attributes, - children); + GECKOBUNDLE_PUT(nodeInfo, + "children", + jni::IntArray::New(children.Elements(), children.Length())); + GECKOBUNDLE_FINISH(nodeInfo); + + return nodeInfo; } diff --git a/accessible/android/AccessibleWrap.h b/accessible/android/AccessibleWrap.h index b88601c33136..d0a04931c4e5 100644 --- a/accessible/android/AccessibleWrap.h +++ b/accessible/android/AccessibleWrap.h @@ -31,25 +31,17 @@ public: virtual bool GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset); - virtual mozilla::java::GeckoBundle::LocalRef ToBundle(); + mozilla::java::GeckoBundle::LocalRef ToBundle(); + + int32_t AndroidClass() + { + return mID == kNoID ? java::SessionAccessibility::CLASSNAME_WEBVIEW + : GetAndroidClass(WrapperRole()); + } static const int32_t kNoID = -1; protected: - mozilla::java::GeckoBundle::LocalRef CreateBundle( - int32_t aParentID, - role aRole, - uint64_t aState, - const nsString& aName, - const nsString& aTextValue, - const nsString& aDOMNodeID, - const nsIntRect& aBounds, - double aCurVal, - double aMinVal, - double aMaxVal, - double aStep, - nsIPersistentProperties* aAttributes, - const nsTArray& aChildren) const; // IDs should be a positive 32bit integer. static int32_t AcquireID(); @@ -62,7 +54,13 @@ protected: int32_t mID; private: - void DOMNodeID(nsString& aDOMNodeID); + virtual AccessibleWrap* WrapperParent() { return static_cast(Parent()); } + + virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep); + + virtual role WrapperRole() { return Role(); } + + virtual void WrapperDOMNodeID(nsString& aDOMNodeID); static void GetRoleDescription(role aRole, nsAString& aGeckoRole, diff --git a/accessible/android/ProxyAccessibleWrap.cpp b/accessible/android/ProxyAccessibleWrap.cpp index b7391c95d766..c417005d072b 100644 --- a/accessible/android/ProxyAccessibleWrap.cpp +++ b/accessible/android/ProxyAccessibleWrap.cpp @@ -72,6 +72,38 @@ ProxyAccessibleWrap::ChildCount() const return Proxy()->ChildrenCount(); } +Accessible* +ProxyAccessibleWrap::GetChildAt(uint32_t aIndex) const +{ + ProxyAccessible* child = Proxy()->ChildAt(aIndex); + return child ? WrapperFor(child) : nullptr; +} + +ENameValueFlag +ProxyAccessibleWrap::Name(nsString& aName) const +{ + Proxy()->Name(aName); + return eNameOK; +} + +void +ProxyAccessibleWrap::Value(nsString& aValue) const +{ + Proxy()->Value(aValue); +} + +uint64_t +ProxyAccessibleWrap::State() +{ + return Proxy()->State(); +} + +nsIntRect +ProxyAccessibleWrap::Bounds() const +{ + return Proxy()->Bounds(); +} + void ProxyAccessibleWrap::ScrollTo(uint32_t aHow) const { @@ -102,46 +134,38 @@ ProxyAccessibleWrap::GetSelectionBounds(int32_t* aStartOffset, return Proxy()->SelectionBoundsAt(0, unused, aStartOffset, aEndOffset); } -mozilla::java::GeckoBundle::LocalRef -ProxyAccessibleWrap::ToBundle() +role +ProxyAccessibleWrap::WrapperRole() { - ProxyAccessible* proxy = Proxy(); - if (!proxy) { - return nullptr; - } - - int32_t parentID = proxy->Parent() ? - WrapperFor(proxy->Parent())->VirtualViewID() : 0; - - nsAutoString name; - proxy->Name(name); - - nsAutoString value; - proxy->Value(value); - - nsAutoString viewIdResourceName; - proxy->DOMNodeID(viewIdResourceName); - - nsCOMPtr attributes = Attributes(); - - auto childCount = proxy->ChildrenCount(); - nsTArray children(childCount); - for (uint32_t i = 0; i < childCount; i++) { - auto child = WrapperFor(proxy->ChildAt(i)); - children.AppendElement(child->VirtualViewID()); - } - - return CreateBundle(parentID, - proxy->Role(), - proxy->State(), - name, - value, - viewIdResourceName, - proxy->Bounds(), - proxy->CurValue(), - proxy->MinValue(), - proxy->MaxValue(), - proxy->Step(), - attributes, - children); + return Proxy()->Role(); +} + +AccessibleWrap* +ProxyAccessibleWrap::WrapperParent() +{ + return Proxy()->Parent() ? WrapperFor(Proxy()->Parent()) : nullptr; +} + +bool +ProxyAccessibleWrap::WrapperRangeInfo(double* aCurVal, + double* aMinVal, + double* aMaxVal, + double* aStep) +{ + if (HasNumericValue()) { + ProxyAccessible* proxy = Proxy(); + *aCurVal = proxy->CurValue(); + *aMinVal = proxy->MinValue(); + *aMaxVal = proxy->MaxValue(); + *aStep = proxy->Step(); + return true; + } + + return false; +} + +void +ProxyAccessibleWrap::WrapperDOMNodeID(nsString& aDOMNodeID) +{ + Proxy()->DOMNodeID(aDOMNodeID); } diff --git a/accessible/android/ProxyAccessibleWrap.h b/accessible/android/ProxyAccessibleWrap.h index 47509d5b48dc..b2fd3902effc 100644 --- a/accessible/android/ProxyAccessibleWrap.h +++ b/accessible/android/ProxyAccessibleWrap.h @@ -34,6 +34,16 @@ public: virtual uint32_t ChildCount() const override; + virtual Accessible* GetChildAt(uint32_t aIndex) const override; + + virtual ENameValueFlag Name(nsString& aName) const override; + + virtual void Value(nsString& aValue) const override; + + virtual uint64_t State() override; + + virtual nsIntRect Bounds() const override; + virtual void ScrollTo(uint32_t aHow) const override; // AccessibleWrap @@ -44,7 +54,15 @@ public: virtual bool GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) override; - virtual mozilla::java::GeckoBundle::LocalRef ToBundle() override; +private: + virtual role WrapperRole() override; + + virtual AccessibleWrap* WrapperParent() override; + + virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep) override; + + virtual void WrapperDOMNodeID(nsString& aDOMNodeID) override; + }; class DocProxyAccessibleWrap : public ProxyAccessibleWrap