Bug 1620324 - Part 2: Make rotor API work with generated root group. r=morgan
☠☠ backed out by 42f436b26f0a ☠ ☠
authorEitan Isaacson <eitan@monotonous.org>
Wed, 16 Sep 2020 20:20:10 +0000
changeset 549007 ea2f00c4049e3bb28bf0a57edba3eeed15a5445e
parent 549006 2ee894a67a931b9a594691081f33156897c89b04
child 549008 e0ebc03307515ca5a2f585578b2419b2087c4253
push id126522
push usereisaacson@mozilla.com
push dateWed, 16 Sep 2020 20:24:07 +0000
treeherderautoland@ea2f00c4049e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmorgan
bugs1620324
milestone82.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1620324 - Part 2: Make rotor API work with generated root group. r=morgan Differential Revision: https://phabricator.services.mozilla.com/D90175
accessible/mac/MOXWebAreaAccessible.h
accessible/mac/MOXWebAreaAccessible.mm
--- a/accessible/mac/MOXWebAreaAccessible.h
+++ b/accessible/mac/MOXWebAreaAccessible.h
@@ -41,39 +41,41 @@ using namespace mozilla::a11y;
 
 - (NSArray*)rootGroupChildren;
 
 - (id)rootGroup;
 
 @end
 
 @interface MOXSearchInfo : NSObject {
-  // The gecko accessible of the web area, we need a reference
+  // The MOX accessible of the web area, we need a reference
   // to set the pivot's root. This is a weak ref.
-  AccessibleOrProxy mWebArea;
+  MOXWebAreaAccessible* mWebArea;
 
-  // The gecko accessible we should start searching from.
+  // The MOX accessible we should start searching from.
   // This is a weak ref.
-  AccessibleOrProxy mStartElem;
+  MOXAccessibleBase* mStartElem;
 
   // The amount of matches we should return
   int mResultLimit;
 
   // The array of search keys to use during this search
   NSMutableArray* mSearchKeys;
 
   // Set to YES if we should search forward, NO if backward
   BOOL mSearchForward;
 
   // Set to YES if we should match on immediate descendants only, NO otherwise
   BOOL mImmediateDescendantsOnly;
 }
 
 - (id)initWithParameters:(NSDictionary*)params
-                 andRoot:(mozilla::a11y::AccessibleOrProxy)root;
+                 andRoot:(MOXWebAreaAccessible*)root;
+
+- (AccessibleOrProxy)startGeckoAccessible;
 
 - (NSMutableArray*)getMatchesForRule:(PivotRule&)rule;
 
 - (NSArray*)performSearch;
 
 - (void)dealloc;
 
 @end
--- a/accessible/mac/MOXWebAreaAccessible.mm
+++ b/accessible/mac/MOXWebAreaAccessible.mm
@@ -171,18 +171,18 @@ using namespace mozilla::a11y;
 }
 
 - (NSArray*)moxUIElementsForSearchPredicate:(NSDictionary*)searchPredicate {
   // Create our search object and set it up with the searchPredicate
   // params. The init function does additional parsing. We pass a
   // reference to the web area (mGeckoAccessible) to use as
   // a start element if one is not specified.
   MOXSearchInfo* search =
-      [[MOXSearchInfo alloc] initWithParameters:searchPredicate
-                                        andRoot:mGeckoAccessible];
+      [[MOXSearchInfo alloc] initWithParameters:searchPredicate andRoot:self];
+
   return [search performSearch];
 }
 
 - (NSNumber*)moxUIElementCountForSearchPredicate:
     (NSDictionary*)searchPredicate {
   return [NSNumber
       numberWithDouble:[[self moxUIElementsForSearchPredicate:searchPredicate]
                            count]];
@@ -257,25 +257,26 @@ using namespace mozilla::a11y;
 
   [super dealloc];
 }
 
 @end
 
 @implementation MOXSearchInfo
 
-- (id)initWithParameters:(NSDictionary*)params andRoot:(AccessibleOrProxy)root {
+- (id)initWithParameters:(NSDictionary*)params
+                 andRoot:(MOXWebAreaAccessible*)root {
   if (id searchKeyParam = [params objectForKey:@"AXSearchKey"]) {
     mSearchKeys = [searchKeyParam isKindOfClass:[NSString class]]
                       ? @[ searchKeyParam ]
                       : searchKeyParam;
   }
 
   if (id startElemParam = [params objectForKey:@"AXStartElement"]) {
-    mStartElem = [startElemParam geckoAccessible];
+    mStartElem = startElemParam;
   } else {
     mStartElem = root;
   }
   MOZ_ASSERT(!mStartElem.IsNull(),
              "Performing search with null gecko accessible!");
 
   mWebArea = root;
 
@@ -285,22 +286,34 @@ using namespace mozilla::a11y;
       [[params objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"];
 
   mImmediateDescendantsOnly =
       [[params objectForKey:@"AXImmediateDescendantsOnly"] boolValue];
 
   return [super init];
 }
 
+- (AccessibleOrProxy)startGeckoAccessible {
+  if ([mStartElem isKindOfClass:[mozAccessible class]]) {
+    return [static_cast<mozAccessible*>(mStartElem) geckoAccessible];
+  }
+
+  // If it isn't a mozAccessible, it doesn't have a gecko accessible
+  // this is most likely the root group. Use the gecko doc as the start
+  // accessible.
+  return [mWebArea geckoAccessible];
+}
+
 - (NSMutableArray*)getMatchesForRule:(PivotRule&)rule {
   int resultLimit = mResultLimit;
   NSMutableArray* matches = [[NSMutableArray alloc] init];
-  Pivot p = Pivot(mWebArea);
-  AccessibleOrProxy match =
-      mSearchForward ? p.Next(mStartElem, rule) : p.Prev(mStartElem, rule);
+  Pivot p = Pivot([mWebArea geckoAccessible]);
+  AccessibleOrProxy geckoStartAcc = [self startGeckoAccessible];
+  AccessibleOrProxy match = mSearchForward ? p.Next(geckoStartAcc, rule)
+                                           : p.Prev(geckoStartAcc, rule);
   while (!match.IsNull() && resultLimit != 0) {
     // we use mResultLimit != 0 to capture the case where mResultLimit is -1
     // when it is set from the params dictionary. If that's true, we want
     // to return all matches (ie. have no limit)
     mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(match);
     if (nativeMatch) {
       // only add/count results for which there is a matching
       // native accessible
@@ -310,62 +323,91 @@ using namespace mozilla::a11y;
 
     match = mSearchForward ? p.Next(match, rule) : p.Prev(match, rule);
   }
 
   return matches;
 }
 
 - (NSArray*)performSearch {
+  AccessibleOrProxy geckoStartAcc = [self startGeckoAccessible];
   NSMutableArray* matches = [[NSMutableArray alloc] init];
   for (id key in mSearchKeys) {
     if ([key isEqualToString:@"AXAnyTypeSearchKey"]) {
-      RotorAllRule rule =
-          mImmediateDescendantsOnly ? RotorAllRule(mStartElem) : RotorAllRule();
+      RotorAllRule rule = mImmediateDescendantsOnly
+                              ? RotorAllRule(geckoStartAcc)
+                              : RotorAllRule();
+
+      if (mSearchForward) {
+        if ([mStartElem isKindOfClass:[MOXWebAreaAccessible class]]) {
+          if (id rootGroup =
+                  [static_cast<MOXWebAreaAccessible*>(mStartElem) rootGroup]) {
+            // Moving forward from web area, rootgroup; if it exists, is next.
+            [matches addObject:rootGroup];
+            if (mResultLimit == 1) {
+              // Found one match, continue in search keys for block.
+              continue;
+            }
+          }
+        } else if (mImmediateDescendantsOnly &&
+                   [mStartElem isKindOfClass:[MOXRootGroup class]]) {
+          // Moving forward from root group. If we don't match descendants,
+          // there is no match. Continue.
+          continue;
+        }
+      } else if (!mSearchForward &&
+                 [mStartElem isKindOfClass:[MOXRootGroup class]]) {
+        // Moving backward from root group. Web area is next.
+        [matches addObject:[mStartElem moxParent]];
+        if (mResultLimit == 1) {
+          // Found one match, continue in search keys for block.
+          continue;
+        }
+      }
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXHeadingSearchKey"]) {
       RotorHeadingRule rule = mImmediateDescendantsOnly
-                                  ? RotorHeadingRule(mStartElem)
+                                  ? RotorHeadingRule(geckoStartAcc)
                                   : RotorHeadingRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXArticleSearchKey"]) {
       RotorArticleRule rule = mImmediateDescendantsOnly
-                                  ? RotorArticleRule(mStartElem)
+                                  ? RotorArticleRule(geckoStartAcc)
                                   : RotorArticleRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXTableSearchKey"]) {
       RotorTableRule rule = mImmediateDescendantsOnly
-                                ? RotorTableRule(mStartElem)
+                                ? RotorTableRule(geckoStartAcc)
                                 : RotorTableRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXLandmarkSearchKey"]) {
       RotorLandmarkRule rule = mImmediateDescendantsOnly
-                                   ? RotorLandmarkRule(mStartElem)
+                                   ? RotorLandmarkRule(geckoStartAcc)
                                    : RotorLandmarkRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXButtonSearchKey"]) {
       RotorButtonRule rule = mImmediateDescendantsOnly
-                                 ? RotorButtonRule(mStartElem)
+                                 ? RotorButtonRule(geckoStartAcc)
                                  : RotorButtonRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
 
     if ([key isEqualToString:@"AXControlSearchKey"]) {
       RotorControlRule rule = mImmediateDescendantsOnly
-                                  ? RotorControlRule(mStartElem)
+                                  ? RotorControlRule(geckoStartAcc)
                                   : RotorControlRule();
       [matches addObjectsFromArray:[self getMatchesForRule:rule]];
     }
   }
 
   return matches;
 }