forked from mirrors/gecko-dev
		
	Bug 1898198: Fix RemoteAccessible::TakeFocus when the browser UI has focus. r=eeejay
Previously, this didn't move the focus at all in this case. Differential Revision: https://phabricator.services.mozilla.com/D211314
This commit is contained in:
		
							parent
							
								
									ebd4094092
								
							
						
					
					
						commit
						f0250b65b5
					
				
					 2 changed files with 90 additions and 1 deletions
				
			
		|  | @ -19,6 +19,7 @@ | ||||||
| #include "nsAccessibilityService.h" | #include "nsAccessibilityService.h" | ||||||
| #include "mozilla/Unused.h" | #include "mozilla/Unused.h" | ||||||
| #include "nsAccUtils.h" | #include "nsAccUtils.h" | ||||||
|  | #include "nsFocusManager.h" | ||||||
| #include "nsTextEquivUtils.h" | #include "nsTextEquivUtils.h" | ||||||
| #include "Pivot.h" | #include "Pivot.h" | ||||||
| #include "Relation.h" | #include "Relation.h" | ||||||
|  | @ -1874,7 +1875,47 @@ bool RemoteAccessible::HasPrimaryAction() const { | ||||||
|   return mCachedFields && mCachedFields->HasAttribute(CacheKey::PrimaryAction); |   return mCachedFields && mCachedFields->HasAttribute(CacheKey::PrimaryAction); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RemoteAccessible::TakeFocus() const { Unused << mDoc->SendTakeFocus(mID); } | void RemoteAccessible::TakeFocus() const { | ||||||
|  |   Unused << mDoc->SendTakeFocus(mID); | ||||||
|  |   if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) { | ||||||
|  |     auto* bp = static_cast<dom::BrowserParent*>(mDoc->Manager()); | ||||||
|  |     MOZ_ASSERT(bp); | ||||||
|  |     dom::Element* owner = bp->GetOwnerElement(); | ||||||
|  |     if (fm->GetFocusedElement() == owner) { | ||||||
|  |       // This remote document tree is already focused. We don't need to do
 | ||||||
|  |       // anything else.
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // Otherwise, we need to focus the <browser> or <iframe> element embedding the
 | ||||||
|  |   // remote document in the parent process. If `this` is in an OOP iframe, we
 | ||||||
|  |   // first need to focus the embedder iframe (and any ancestor OOP iframes). If
 | ||||||
|  |   // the parent process embedder element were already focused, that would happen
 | ||||||
|  |   // automatically, but it isn't. We can't simply focus the parent process
 | ||||||
|  |   // embedder element before calling mDoc->SendTakeFocus because that would
 | ||||||
|  |   // cause the remote document to restore focus to the last focused element,
 | ||||||
|  |   // which we don't want.
 | ||||||
|  |   DocAccessibleParent* embeddedDoc = mDoc; | ||||||
|  |   Accessible* embedder = mDoc->Parent(); | ||||||
|  |   while (embedder) { | ||||||
|  |     MOZ_ASSERT(embedder->IsOuterDoc()); | ||||||
|  |     RemoteAccessible* embedderRemote = embedder->AsRemote(); | ||||||
|  |     if (!embedderRemote) { | ||||||
|  |       // This is the element in the parent process which embeds the remote
 | ||||||
|  |       // document.
 | ||||||
|  |       embedder->TakeFocus(); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     // This is a remote <iframe>.
 | ||||||
|  |     if (embeddedDoc->IsTopLevelInContentProcess()) { | ||||||
|  |       // We only need to focus OOP iframes because these are where we cross
 | ||||||
|  |       // process boundaries.
 | ||||||
|  |       Unused << embedderRemote->mDoc->SendTakeFocus(embedderRemote->mID); | ||||||
|  |     } | ||||||
|  |     embeddedDoc = embedderRemote->mDoc; | ||||||
|  |     embedder = embeddedDoc->Parent(); | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void RemoteAccessible::ScrollTo(uint32_t aHow) const { | void RemoteAccessible::ScrollTo(uint32_t aHow) const { | ||||||
|   Unused << mDoc->SendScrollTo(mID, aHow); |   Unused << mDoc->SendScrollTo(mID, aHow); | ||||||
|  |  | ||||||
|  | @ -71,3 +71,51 @@ addAccessibleTask( | ||||||
|   }, |   }, | ||||||
|   { topLevel: false, iframe: true, remoteIframe: true } |   { topLevel: false, iframe: true, remoteIframe: true } | ||||||
| ); | ); | ||||||
|  | 
 | ||||||
|  | function focusURLBar() { | ||||||
|  |   info("Focusing the URL bar"); | ||||||
|  |   const focused = waitForEvent( | ||||||
|  |     EVENT_FOCUS, | ||||||
|  |     event => event.accessible.role == ROLE_ENTRY | ||||||
|  |   ); | ||||||
|  |   gURLBar.focus(); | ||||||
|  |   return focused; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Test takeFocus on web content when focus is in the browser UI. | ||||||
|  |  */ | ||||||
|  | addAccessibleTask( | ||||||
|  |   ` | ||||||
|  | <button id="outerButton">outerButton</button> | ||||||
|  | <iframe src="data:text/html,<body id='innerDoc'><button id='innerButton'>innerButton</button>"></iframe> | ||||||
|  |   `,
 | ||||||
|  |   async function testFocusContentWhileUiFocused(browser, docAcc) { | ||||||
|  |     await focusURLBar(); | ||||||
|  |     info("Focusing docAcc"); | ||||||
|  |     let focused = waitForEvent(EVENT_FOCUS, docAcc); | ||||||
|  |     docAcc.takeFocus(); | ||||||
|  |     await focused; | ||||||
|  | 
 | ||||||
|  |     await focusURLBar(); | ||||||
|  |     info("Focusing outerButton"); | ||||||
|  |     const outerButton = findAccessibleChildByID(docAcc, "outerButton"); | ||||||
|  |     focused = waitForEvent(EVENT_FOCUS, outerButton); | ||||||
|  |     outerButton.takeFocus(); | ||||||
|  |     await focused; | ||||||
|  | 
 | ||||||
|  |     await focusURLBar(); | ||||||
|  |     info("Focusing innerButton"); | ||||||
|  |     const innerButton = findAccessibleChildByID(docAcc, "outerButton"); | ||||||
|  |     focused = waitForEvent(EVENT_FOCUS, innerButton); | ||||||
|  |     innerButton.takeFocus(); | ||||||
|  |     await focused; | ||||||
|  | 
 | ||||||
|  |     await focusURLBar(); | ||||||
|  |     info("Focusing outerButton"); | ||||||
|  |     focused = waitForEvent(EVENT_FOCUS, outerButton); | ||||||
|  |     outerButton.takeFocus(); | ||||||
|  |     await focused; | ||||||
|  |   }, | ||||||
|  |   { chrome: true, topLevel: true, iframe: true, remoteIframe: true } | ||||||
|  | ); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 James Teh
						James Teh