mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-06 00:10:25 +00:00
Bug 1642707: Add web area class and attributes r=eeejay
Differential Revision: https://phabricator.services.mozilla.com/D80473
This commit is contained in:
parent
537f656a8e
commit
117fa600ac
@ -12,6 +12,7 @@
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#import "MOXMathAccessibles.h"
|
||||
#import "MOXWebAreaAccessible.h"
|
||||
#import "mozAccessible.h"
|
||||
#import "mozActionElements.h"
|
||||
#import "mozHTMLAccessible.h"
|
||||
@ -174,6 +175,9 @@ Class a11y::GetTypeFromRole(roles::Role aRole) {
|
||||
case roles::COMBOBOX:
|
||||
return [mozPopupButtonAccessible class];
|
||||
|
||||
case roles::DOCUMENT:
|
||||
return [MOXWebAreaAccessible class];
|
||||
|
||||
case roles::PUSHBUTTON:
|
||||
return [mozButtonAccessible class];
|
||||
|
||||
|
@ -129,6 +129,25 @@
|
||||
// AXMenuItemMarkChar
|
||||
- (NSString* _Nullable)moxMenuItemMarkChar;
|
||||
|
||||
// AXLoaded
|
||||
- (NSNumber* _Nullable)moxLoaded;
|
||||
|
||||
// AXLoadingProgress
|
||||
- (NSNumber* _Nullable)moxLoadingProgress;
|
||||
|
||||
// Webkit also implements the following:
|
||||
// // AXCaretBrowsingEnabled
|
||||
// - (NSString* _Nullable)moxCaretBrowsingEnabled;
|
||||
|
||||
// // AXLayoutCount
|
||||
// - (NSString* _Nullable)moxLayoutCount;
|
||||
|
||||
// // AXWebSessionID
|
||||
// - (NSString* _Nullable)moxWebSessionID;
|
||||
|
||||
// // AXPreventKeyboardDOMEventDispatch
|
||||
// - (NSString* _Nullable)moxPreventKeyboardDOMEventDispatch;
|
||||
|
||||
// Table Attributes
|
||||
|
||||
// AXRowCount
|
||||
|
23
accessible/mac/MOXWebAreaAccessible.h
Normal file
23
accessible/mac/MOXWebAreaAccessible.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
@interface MOXWebAreaAccessible : mozAccessible
|
||||
// overrides
|
||||
- (NSURL* _Nullable)moxURL;
|
||||
|
||||
// overrides
|
||||
- (NSNumber* _Nullable)moxLoaded;
|
||||
|
||||
// overrides
|
||||
- (NSNumber* _Nullable)moxLoadingProgress;
|
||||
|
||||
// overrides
|
||||
- (void)handleAccessibleEvent:(uint32_t)eventType;
|
||||
|
||||
@end
|
88
accessible/mac/MOXWebAreaAccessible.mm
Normal file
88
accessible/mac/MOXWebAreaAccessible.mm
Normal file
@ -0,0 +1,88 @@
|
||||
/* -*- (Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset:) 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "MOXWebAreaAccessible.h"
|
||||
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "DocAccessibleParent.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
@implementation MOXWebAreaAccessible
|
||||
|
||||
- (NSURL* _Nullable)moxURL {
|
||||
if ([self isExpired]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
nsAutoString url;
|
||||
if (mGeckoAccessible.IsAccessible()) {
|
||||
MOZ_ASSERT(mGeckoAccessible.AsAccessible()->IsDoc());
|
||||
DocAccessible* acc = mGeckoAccessible.AsAccessible()->AsDoc();
|
||||
acc->URL(url);
|
||||
} else {
|
||||
ProxyAccessible* proxy = mGeckoAccessible.AsProxy();
|
||||
proxy->URL(url);
|
||||
}
|
||||
|
||||
if (url.IsEmpty()) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSURL URLWithString:nsCocoaUtils::ToNSString(url)];
|
||||
}
|
||||
|
||||
- (NSNumber* _Nullable)moxLoaded {
|
||||
if ([self isExpired]) {
|
||||
return nil;
|
||||
}
|
||||
// We are loaded if we aren't busy or stale
|
||||
return @([self stateWithMask:(states::BUSY & states::STALE)] == 0);
|
||||
}
|
||||
|
||||
// overrides
|
||||
- (NSNumber* _Nullable)moxLoadingProgress {
|
||||
if ([self isExpired]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([self stateWithMask:states::STALE] != 0) {
|
||||
// We expose stale state until the document is ready (DOM is loaded and tree is
|
||||
// constructed) so we indicate load hasn't started while this state is present.
|
||||
return @0.0;
|
||||
}
|
||||
|
||||
if ([self stateWithMask:states::BUSY] != 0) {
|
||||
// We expose state busy until the document and all its subdocuments are completely
|
||||
// loaded, so we indicate partial loading here
|
||||
return @0.5;
|
||||
}
|
||||
|
||||
// if we are not busy and not stale, we are loaded
|
||||
return @1.0;
|
||||
}
|
||||
|
||||
- (void)handleAccessibleEvent:(uint32_t)eventType {
|
||||
switch (eventType) {
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
[self moxPostNotification:NSAccessibilityFocusedUIElementChangedNotification];
|
||||
if ((mGeckoAccessible.IsProxy() && mGeckoAccessible.AsProxy()->IsDoc() &&
|
||||
mGeckoAccessible.AsProxy()->AsDoc()->IsTopLevel()) ||
|
||||
(mGeckoAccessible.IsAccessible() && !mGeckoAccessible.AsAccessible()->IsRoot() &&
|
||||
mGeckoAccessible.AsAccessible()->AsDoc()->ParentDocument()->IsRoot())) {
|
||||
// we fire an AXLoadComplete event on top-level documents only
|
||||
[self moxPostNotification:@"AXLoadComplete"];
|
||||
} else {
|
||||
// otherwise the doc belongs to an iframe (IsTopLevelInContentProcess)
|
||||
// and we fire AXLayoutComplete instead
|
||||
[self moxPostNotification:@"AXLayoutComplete"];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
[super handleAccessibleEvent:eventType];
|
||||
}
|
||||
|
||||
@end
|
@ -64,13 +64,15 @@ void ProxyDestroyed(ProxyAccessible* aProxy) {
|
||||
}
|
||||
|
||||
void ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType) {
|
||||
// ignore everything but focus-changed, value-changed, caret and selection
|
||||
// events for now.
|
||||
// ignore everything but focus-changed, value-changed, caret,
|
||||
// selection, and document load complete events for now.
|
||||
NSLog(@"Event type is %u", aEventType);
|
||||
if (aEventType != nsIAccessibleEvent::EVENT_FOCUS &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_REORDER)
|
||||
return;
|
||||
|
||||
|
@ -19,6 +19,7 @@ UNIFIED_SOURCES += [
|
||||
'MacUtils.mm',
|
||||
'MOXAccessibleBase.mm',
|
||||
'MOXMathAccessibles.mm',
|
||||
'MOXWebAreaAccessible.mm',
|
||||
'mozAccessible.mm',
|
||||
'mozActionElements.mm',
|
||||
'mozHTMLAccessible.mm',
|
||||
|
@ -70,6 +70,8 @@ inline mozAccessible* GetNativeFromGeckoAccessible(mozilla::a11y::AccessibleOrPr
|
||||
|
||||
// Given a gecko accessibility event type, post the relevant
|
||||
// system accessibility notification.
|
||||
// Note: when overriding or adding new events, make sure your events aren't
|
||||
// filtered out in Platform::ProxyEvent or AccessibleWrap::HandleAccEvent!
|
||||
- (void)handleAccessibleEvent:(uint32_t)eventType;
|
||||
|
||||
// internal method to retrieve a child at a given index.
|
||||
|
@ -178,7 +178,7 @@ static const uint64_t kCacheInitialized = ((uint64_t)0x1) << 63;
|
||||
// These accessible types are the exception to the rule of label vs. title:
|
||||
// They may be named explicitly, but they still provide a label not a title.
|
||||
return mRole == roles::GROUPING || mRole == roles::RADIO_GROUP || mRole == roles::FIGURE ||
|
||||
mRole == roles::GRAPHIC;
|
||||
mRole == roles::GRAPHIC || mRole == roles::DOCUMENT;
|
||||
}
|
||||
|
||||
- (mozilla::a11y::AccessibleOrProxy)geckoAccessible {
|
||||
@ -794,11 +794,6 @@ struct RoleDescrComparator {
|
||||
case nsIAccessibleEvent::EVENT_FOCUS:
|
||||
[self moxPostNotification:NSAccessibilityFocusedUIElementChangedNotification];
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
[self moxPostNotification:NSAccessibilityFocusedUIElementChangedNotification];
|
||||
[self moxPostNotification:@"AXLoadComplete"];
|
||||
[self moxPostNotification:@"AXLayoutComplete"];
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
|
||||
[self moxPostNotification:@"AXMenuOpened"];
|
||||
break;
|
||||
|
@ -26,3 +26,4 @@ support-files =
|
||||
[browser_mathml.js]
|
||||
[browser_input.js]
|
||||
[browser_focus.js]
|
||||
[browser_webarea.js]
|
||||
|
64
accessible/tests/browser/mac/browser_webarea.js
Normal file
64
accessible/tests/browser/mac/browser_webarea.js
Normal file
@ -0,0 +1,64 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
|
||||
|
||||
// Test web area role and AXLoadComplete event
|
||||
addAccessibleTask(``, async (browser, accDoc) => {
|
||||
let evt = waitForMacEvent("AXLoadComplete");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
content.location = "data:text/html,<title>webarea test</title>";
|
||||
});
|
||||
let doc = await evt;
|
||||
|
||||
is(
|
||||
doc.getAttributeValue("AXRole"),
|
||||
"AXWebArea",
|
||||
"document has AXWebArea role"
|
||||
);
|
||||
is(doc.getAttributeValue("AXValue"), "", "document has no AXValue");
|
||||
is(doc.getAttributeValue("AXTitle"), null, "document has no AXTitle");
|
||||
is(
|
||||
doc.getAttributeValue("AXDescription"),
|
||||
"webarea test",
|
||||
"test has correct label"
|
||||
);
|
||||
|
||||
is(doc.getAttributeValue("AXLoaded"), 1, "document has finished loading");
|
||||
});
|
||||
|
||||
// Test iframe web area role and AXLayoutComplete event
|
||||
addAccessibleTask(`<title>webarea test</title>`, async (browser, accDoc) => {
|
||||
// We should get a layout complete after the page content
|
||||
// loads, so we start the await here.
|
||||
let evt = waitForMacEvent("AXLayoutComplete");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
const iframe = content.document.createElement("iframe");
|
||||
iframe.src = "data:text/html,hello world";
|
||||
content.document.body.appendChild(iframe);
|
||||
});
|
||||
let doc = await evt;
|
||||
|
||||
is(
|
||||
doc.getAttributeValue("AXRole"),
|
||||
"AXWebArea",
|
||||
"iframe document has AXWebArea role"
|
||||
);
|
||||
is(doc.getAttributeValue("AXValue"), "", "iframe document has no AXValue");
|
||||
is(doc.getAttributeValue("AXTitle"), null, "iframe document has no AXTitle");
|
||||
is(
|
||||
doc.getAttributeValue("AXDescription"),
|
||||
"data:text/html,hello world",
|
||||
"test has correct label"
|
||||
);
|
||||
|
||||
is(
|
||||
doc.getAttributeValue("AXLoaded"),
|
||||
1,
|
||||
"iframe document has finished loading"
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue
Block a user