--- a/.clang-format
+++ b/.clang-format
@@ -23,8 +23,16 @@ NS_INTERFACE_MAP_END|\
NS_IMPL_CYCLE_COLLECTION_.*_END|\
NS_INTERFACE_TABLE_END|\
NS_INTERFACE_MAP_END_INHERITING|\
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END_INHERITED|\
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED$"
SortIncludes: false
+
+# All of the following items are default
+# in the Mozila coding style from clang format 4.0
+AlwaysBreakAfterReturnType: TopLevel
+BinPackArguments: false
+BinPackParameters: false
+SpaceAfterTemplateKeyword: false
+ReflowComments: false
--- a/.clang-format-ignore
+++ b/.clang-format-ignore
@@ -1,12 +1,18 @@
^build/clang-plugin/tests/.*
^config/gcc-stl-wrapper.template.h
^config/msvc-stl-wrapper.template.h
^js/src/jsapi-tests/.*
+^widget/android/GeneratedJNINatives.h
+^widget/android/GeneratedJNIWrappers.cpp
+^widget/android/GeneratedJNIWrappers.h
+^widget/android/fennec/FennecJNINatives.h
+^widget/android/fennec/FennecJNIWrappers.cpp
+^widget/android/fennec/FennecJNIWrappers.h
# Generated from ./tools/rewriting/ThirdPartyPaths.txt
# awk '{print "^"$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt
^browser/components/translation/cld2/.*
^build/stlport/.*
^db/sqlite3/src/.*
^dom/media/platforms/ffmpeg/libav.*
^extensions/spellcheck/hunspell/src/.*
@@ -14,57 +20,63 @@
^gfx/2d/image_operations.*
^gfx/angle/.*
^gfx/cairo/.*
^gfx/graphite2/.*
^gfx/harfbuzz/.*
^gfx/ots/.*
^gfx/qcms/.*
^gfx/skia/.*
+^gfx/webrender.*
+^gfx/webrender_traits.*
^gfx/ycbcr/.*
^intl/hyphenation/hyphen/.*
^intl/icu/.*
^ipc/chromium/.*
^js/src/ctypes/libffi/.*
^js/src/dtoa.c.*
^js/src/jit/arm64/vixl/.*
^media/gmp-clearkey/0.1/openaes/.*
^media/kiss_fft/.*
+^media/ffvpx/.*
^media/libav/.*
^media/libcubeb/.*
^media/libjpeg/.*
^media/libmkv/.*
^media/libnestegg/.*
^media/libogg/.*
^media/libopus/.*
^media/libpng/.*
^media/libsoundtouch/.*
^media/libspeex_resampler/.*
^media/libstagefright/.*
^media/libtheora/.*
^media/libtremor/.*
^media/libvorbis/.*
^media/libvpx/.*
^media/libyuv/.*
-^media/mtransport/.*
+^media/mtransport/third_party/.*
^media/openmax_dl/.*
^media/pocketsphinx/.*
^media/sphinxbase/.*
^media/webrtc/trunk/.*
+^media/webrtc/signaling/src/sdp/sipcc/.*
^memory/jemalloc/src/.*
^mfbt/decimal/.*
-^mfbt/double-conversion/.*
+^mfbt/double-conversion/source/.*
^mfbt/lz4.*
^mobile/android/thirdparty/.*
^modules/brotli/.*
+^modules/fdlibm/.*
^modules/freetype2/.*
^modules/libbz2/.*
^modules/libmar/.*
^modules/zlib/.*
^netwerk/sctp/src/.*
^netwerk/srtp/src/.*
^nsprpub/.*
^other-licenses/.*
+^parser/expat/.*
^security/sandbox/chromium/.*
^testing/gtest/gmock/.*
^testing/gtest/gtest/.*
^toolkit/components/protobuf/.*
^toolkit/crashreporter/google-breakpad/.*
new file mode 100644
--- /dev/null
+++ b/.cron.yml
@@ -0,0 +1,61 @@
+# Definitions for jobs that run periodically. For details on the format, see
+# `taskcluster/taskgraph/cron/schema.py`. For documentation, see
+# `taskcluster/docs/cron.rst`.
+
+jobs:
+ - name: nightly-desktop
+ job:
+ type: decision-task
+ treeherder-symbol: Nd
+ triggered-by: nightly
+ target-tasks-method: nightly_linux
+ run-on-projects:
+ - mozilla-central
+ - mozilla-aurora
+ - date
+ when:
+ by-project:
+ # Match buildbot starts for now
+ date: [{hour: 16, minute: 0}]
+ mozilla-central: [{hour: 11, minute: 0}]
+ mozilla-aurora: [{hour: 8, minute: 45}] # Buildbot uses minute 40
+ # No default
+
+ - name: nightly-android
+ job:
+ type: decision-task
+ treeherder-symbol: Na
+ triggered-by: nightly
+ target-tasks-method: nightly_fennec
+ run-on-projects:
+ - mozilla-central
+ - mozilla-aurora
+ - date
+ when:
+ by-project:
+ # Match buildbot starts for now
+ date: [{hour: 16, minute: 0}]
+ mozilla-central: [{hour: 11, minute: 0}]
+ mozilla-aurora: [{hour: 8, minute: 45}] # Buildbot uses minute 40
+ # No default
+
+ - name: nightly-mochitest-valgrind
+ job:
+ type: decision-task
+ treeherder-symbol: Vg
+ target-tasks-method: mochitest_valgrind
+ run-on-projects:
+ - mozilla-central
+ when:
+ - {hour: 16, minute: 0}
+ - {hour: 4, minute: 0}
+
+ - name: nightly-code-coverage
+ job:
+ type: decision-task
+ treeherder-symbol: Nc
+ target-tasks-method: nightly_code_coverage
+ run-on-projects:
+ - mozilla-central
+ when:
+ - {hour: 18, minute: 0}
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,196 +1,267 @@
# Always ignore node_modules.
**/node_modules/**/*.*
# Exclude expected objdirs.
obj*/**
# We ignore all these directories by default, until we get them enabled.
# If you are enabling a directory, please add directory specific exclusions
-# below.
+# below.
addon-sdk/**
build/**
caps/**
chrome/**
config/**
db/**
docshell/**
-dom/**
editor/**
embedding/**
extensions/**
gfx/**
gradle/**
hal/**
image/**
intl/**
ipc/**
-js/**
layout/**
media/**
memory/**
mfbt/**
modules/**
mozglue/**
netwerk/**
nsprpub/**
other-licenses/**
parser/**
probes/**
python/**
rdf/**
+servo/**
startupcache/**
testing/**
-!tools/lint/eslint/eslint-plugin-mozilla/
-tools/lint/eslint/eslint-plugin-mozilla/node_modules/**
-tools/**
+tools/update-packaging/**
uriloader/**
view/**
widget/**
xpcom/**
xpfe/**
xulrunner/**
# b2g exclusions (pref files).
b2g/app/b2g.js
b2g/graphene/graphene.js
b2g/locales/en-US/b2g-l10n.js
# browser/ exclusions
browser/app/**
browser/branding/**/firefox-branding.js
-browser/base/content/browser-social.js
browser/base/content/nsContextMenu.js
browser/base/content/sanitizeDialog.js
browser/base/content/test/general/file_csp_block_all_mixedcontent.html
browser/base/content/test/urlbar/file_blank_but_not_blank.html
browser/base/content/newtab/**
browser/components/downloads/**
-browser/components/privatebrowsing/**
-browser/components/sessionstore/**
+# Test files that are really json not js, and don't need to be linted.
+browser/components/sessionstore/test/unit/data/sessionstore_valid.js
+browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
browser/components/tabview/**
-# generated files in cld2
-browser/components/translation/cld2/cld-worker.js
-browser/extensions/pdfjs/**
+# generated & special files in cld2
+browser/components/translation/cld2/**
+browser/extensions/pdfjs/content/build**
+browser/extensions/pdfjs/content/web**
# generated or library files in pocket
browser/extensions/pocket/content/panels/js/tmpl.js
browser/extensions/pocket/content/panels/js/vendor/**
browser/locales/**
+# imported from chromium
+browser/extensions/mortar/**
# devtools/ exclusions
devtools/client/canvasdebugger/**
devtools/client/commandline/**
devtools/client/debugger/**
devtools/client/framework/**
!devtools/client/framework/selection.js
-!devtools/client/framework/toolbox.js
-devtools/client/jsonview/lib/**
-devtools/client/memory/**
-devtools/client/netmonitor/test/**
-devtools/client/netmonitor/har/test/**
+!devtools/client/framework/target*
+!devtools/client/framework/toolbox*
+devtools/client/inspector/markup/test/doc_markup_events_*.html
+devtools/client/inspector/rules/test/doc_media_queries.html
+devtools/client/memory/test/chrome/*.html
+devtools/client/performance/components/test/test_jit_optimizations_01.html
devtools/client/projecteditor/**
-devtools/client/promisedebugger/**
+devtools/client/responsive.html/test/browser/touch.html
devtools/client/responsivedesign/**
+!devtools/client/responsivedesign/responsivedesign.jsm
devtools/client/scratchpad/**
devtools/client/shadereditor/**
devtools/client/shared/*.jsm
+devtools/client/shared/components/reps/reps.js
+devtools/client/shared/components/reps/test/mochitest/*.html
+!devtools/client/shared/components/reps/test/mochitest/test_reps_infinity.html
+!devtools/client/shared/components/reps/test/mochitest/test_reps_nan.html
+!devtools/client/shared/components/reps/test/mochitest/test_reps_promise.html
+!devtools/client/shared/components/reps/test/mochitest/test_reps_symbol.html
+!devtools/client/shared/components/reps/test/mochitest/test_reps_text-node.html
+devtools/client/shared/components/test/mochitest/*.html
+!devtools/client/shared/components/test/mochitest/test_stack-trace.html
+devtools/client/shared/shim/test/test_*.html
+devtools/client/shared/test/browser_toolbar_webconsole_errors_count.html
devtools/client/shared/webgl-utils.js
devtools/client/shared/widgets/*.jsm
+devtools/client/storage/test/*.html
+!devtools/client/storage/test/storage-cookies.html
+!devtools/client/storage/test/storage-overflow.html
+!devtools/client/storage/test/storage-search.html
+!devtools/client/storage/test/storage-unsecured-iframe.html
+!devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html
devtools/client/webaudioeditor/**
devtools/client/webconsole/net/**
devtools/client/webconsole/test/**
devtools/client/webconsole/console-output.js
devtools/client/webconsole/hudservice.js
-devtools/client/webconsole/utils.js
devtools/client/webconsole/webconsole-connection-proxy.js
devtools/client/webconsole/webconsole.js
devtools/client/webide/**
!devtools/client/webide/components/webideCli.js
-devtools/server/*.js
-devtools/server/*.jsm
-!devtools/server/child.js
-!devtools/server/css-logic.js
-!devtools/server/main.js
-!devtools/server/websocket-server.js
-devtools/server/actors/**
-!devtools/server/actors/csscoverage.js
-!devtools/server/actors/inspector.js
-!devtools/server/actors/highlighters/css-grid.js
-!devtools/server/actors/highlighters/eye-dropper.js
-!devtools/server/actors/layout.js
-!devtools/server/actors/string.js
-!devtools/server/actors/styles.js
-!devtools/server/actors/tab.js
-!devtools/server/actors/webbrowser.js
-!devtools/server/actors/webextension.js
-!devtools/server/actors/webextension-inspected-window.js
-devtools/server/performance/**
-devtools/server/tests/browser/**
-!devtools/server/tests/browser/browser_webextension_inspected_window.js
-devtools/server/tests/mochitest/**
-devtools/server/tests/unit/**
-devtools/shared/apps/**
-devtools/shared/client/**
-devtools/shared/discovery/**
-devtools/shared/gcli/**
-!devtools/shared/gcli/templater.js
-devtools/shared/heapsnapshot/**
-devtools/shared/layout/**
-devtools/shared/locales/**
-devtools/shared/performance/**
-!devtools/shared/platform/**
-devtools/shared/qrcode/**
-devtools/shared/security/**
-devtools/shared/shims/**
-devtools/shared/tests/**
-!devtools/shared/tests/unit/test_csslexer.js
-devtools/shared/touch/**
-devtools/shared/transport/**
-!devtools/shared/transport/transport.js
-!devtools/shared/transport/websocket-transport.js
-devtools/shared/webconsole/test/**
-devtools/shared/worker/**
-!devtools/shared/worker/worker.js
+devtools/server/actors/webconsole.js
+devtools/server/actors/object.js
+devtools/server/actors/script.js
+devtools/server/actors/styleeditor.js
+devtools/server/actors/stylesheets.js
+devtools/server/tests/browser/storage-*.html
+!devtools/server/tests/browser/storage-unsecured-iframe.html
+devtools/server/tests/browser/stylesheets-nested-iframes.html
+devtools/server/tests/unit/xpcshell_debugging_script.js
+devtools/shared/platform/content/test/test_clipboard.html
+devtools/shared/qrcode/tests/mochitest/test_decode.html
+devtools/shared/tests/mochitest/*.html
+devtools/shared/webconsole/test/test_*.html
# Ignore devtools pre-processed files
devtools/client/framework/toolbox-process-window.js
devtools/client/performance/system.js
devtools/client/webide/webide-prefs.js
devtools/client/preferences/**
# Ignore devtools third-party libs
devtools/shared/jsbeautify/*
devtools/shared/acorn/*
-devtools/client/sourceeditor/tern/*
+devtools/shared/gcli/source/*
devtools/shared/node-properties/*
devtools/shared/pretty-fast/*
devtools/shared/sourcemap/*
devtools/shared/sprintfjs/*
devtools/shared/qrcode/decoder/*
devtools/shared/qrcode/encoder/*
devtools/client/shared/demangle.js
+devtools/client/shared/source-map/*
devtools/client/shared/vendor/*
devtools/client/sourceeditor/codemirror/*.js
devtools/client/sourceeditor/codemirror/**/*.js
+devtools/client/sourceeditor/tern/*
devtools/client/sourceeditor/test/cm_mode_ruby.js
devtools/client/sourceeditor/test/codemirror/*
devtools/client/inspector/markup/test/lib_*
devtools/client/jsonview/lib/require.js
devtools/server/actors/utils/automation-timeline.js
# Ignore devtools files testing sourcemaps / code style
devtools/client/debugger/test/mochitest/code_binary_search.js
devtools/client/debugger/test/mochitest/code_math.min.js
devtools/client/debugger/test/mochitest/code_math_bogus_map.js
devtools/client/debugger/test/mochitest/code_ugly*
devtools/client/debugger/test/mochitest/code_worker-source-map.js
devtools/client/framework/test/code_ugly*
devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
devtools/server/tests/unit/setBreakpoint*
+devtools/server/tests/unit/sourcemapped.js
+
+# dom/ exclusions
+dom/animation/**
+dom/archivereader/**
+dom/asmjscache/**
+dom/audiochannel/**
+dom/base/**
+dom/battery/**
+dom/bindings/**
+dom/broadcastchannel/**
+dom/browser-element/**
+dom/cache/**
+dom/canvas/**
+dom/commandhandler/**
+dom/console/**
+dom/crypto/**
+dom/devicestorage/**
+dom/encoding/**
+dom/events/**
+dom/fetch/**
+dom/file/**
+dom/filehandle/**
+dom/filesystem/**
+dom/flyweb/**
+dom/gamepad/**
+dom/geolocation/**
+dom/grid/**
+dom/html/**
+dom/imptests/**
+dom/interfaces/**
+dom/ipc/**
+dom/json/**
+dom/jsurl/**
+dom/locales/**
+dom/manifest/**
+dom/mathml/**
+dom/media/**
+dom/messagechannel/**
+dom/network/**
+dom/notification/**
+dom/offline/**
+dom/performance/**
+dom/permission/**
+dom/plugins/**
+dom/power/**
+dom/presentation/**
+dom/promise/**
+dom/push/**
+dom/quota/**
+dom/res/**
+dom/secureelement/**
+dom/security/**
+dom/smil/**
+dom/storage/**
+dom/svg/**
+dom/system/**
+dom/tests/**
+dom/time/**
+dom/u2f/**
+dom/url/**
+dom/vr/**
+dom/webauthn/**
+dom/webbrowserpersist/**
+dom/webidl/**
+dom/workers/**
+dom/worklet/**
+dom/xbl/**
+dom/xhr/**
+dom/xml/**
+dom/xslt/**
+dom/xul/**
+
+# Exclude everything but self-hosted JS
+js/ductwork/**
+js/examples/**
+js/ipc/**
+js/public/**
+js/xpconnect/**
+js/src/devtools/**
+js/src/octane/**
+js/src/jit-test/**
+js/src/tests/**
# mobile/android/ exclusions
mobile/android/tests/
# Uses `#filter substitution`
mobile/android/b2gdroid/app/b2gdroid.js
mobile/android/app/mobile.js
mobile/android/chrome/content/healthreport-prefs.js
@@ -204,20 +275,32 @@ mobile/android/locales/
# Non-standard `(catch ex if ...)`
mobile/android/chrome/content/browser.js
mobile/android/components/Snippets.js
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
mobile/android/modules/HomeProvider.jsm
+# security/ exclusions (pref files).
+security/manager/ssl/security-prefs.js
+
+#NSS
+security/nss/**
+
# services/ exclusions
# Uses `#filter substitution`
services/sync/modules/constants.js
+services/sync/services-sync.js
+
+# Third party services
+services/common/kinto-http-client.js
+services/common/kinto-offline-client.js
+services/sync/tps/extensions/mozmill
# toolkit/ exclusions
# Not part of the default build
toolkit/components/help/**
# Intentionally invalid JS
toolkit/components/workerloader/tests/moduleF-syntax-error.js
@@ -225,28 +308,25 @@ toolkit/components/workerloader/tests/mo
# Tests old non-star function generators
toolkit/modules/tests/xpcshell/test_task.js
# Not yet updated
toolkit/components/osfile/**
# External code:
toolkit/components/microformats/test/**
+toolkit/components/microformats/microformat-shiv.js
toolkit/components/reader/Readability.js
toolkit/components/reader/JSDOMParser.js
# Uses preprocessing
toolkit/content/widgets/wizard.xml
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/url-classifier/**
toolkit/components/urlformatter/nsURLFormatter.js
-toolkit/identity/FirefoxAccounts.jsm
toolkit/modules/AppConstants.jsm
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/internal/AddonConstants.jsm
toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
toolkit/webapps/**
# Third party
toolkit/modules/third_party/**
-
-#NSS
-security/nss/**
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,17 +1,24 @@
"use strict";
module.exports = {
// When adding items to this file please check for effects on sub-directories.
"plugins": [
"mozilla"
],
"rules": {
+ "mozilla/avoid-removeChild": "error",
+ "mozilla/avoid-nsISupportsString-preferences": "error",
"mozilla/import-globals": "warn",
+ "mozilla/no-import-into-var-and-global": "error",
+ "mozilla/no-useless-parameters": "error",
+ "mozilla/no-useless-removeEventListener": "error",
+ "mozilla/use-default-preference-values": "error",
+ "mozilla/use-ownerGlobal": "error",
// No (!foo in bar) or (!object instanceof Class)
"no-unsafe-negation": "error",
},
"env": {
"es6": true
},
"parserOptions": {
--- a/.hgignore
+++ b/.hgignore
@@ -39,16 +39,18 @@
# SpiderMonkey configury
^js/src/configure$
^js/src/old-configure$
^js/src/autom4te.cache$
# SpiderMonkey test result logs
^js/src/tests/results-.*\.(html|txt)$
^js/src/devtools/rootAnalysis/t/out
+# SpiderMonkey clone of the webassembly spec repository
+^js/src/wasm/spec
# Java HTML5 parser classes
^parser/html/java/(html|java)parser/
# SVN directories
\.svn/
# Ignore the files and directory that Eclipse IDE creates
@@ -129,8 +131,11 @@ GPATH
^testing/talos/talos/tests/devtools/damp.manifest.develop
^talos-venv
# Ignore files created when running a reftest.
^lextab.py$
# tup database
^\.tup
+
+subinclude:servo/.hgignore
+
--- a/.hgtags
+++ b/.hgtags
@@ -125,8 +125,10 @@ 67a788db9f07822cfef52351bbbe3745dff8bd7f
99137d6d4061f408ae0869122649d8bdf489cc30 FIREFOX_AURORA_45_BASE
67c66c2878aed17ae3096d7db483ddbb2293c503 FIREFOX_AURORA_46_BASE
68d3781deda0d4d58ec9877862830db89669b3a5 FIREFOX_AURORA_47_BASE
1c6385ae1fe7e37d8f23f958ce14582f07af729e FIREFOX_AURORA_48_BASE
d98f20c25feeac4dd7ebbd1c022957df1ef58af4 FIREFOX_AURORA_49_BASE
465d150bc8be5bbf9f02a8607d4552b6a5e1697c FIREFOX_AURORA_50_BASE
fc69febcbf6c0dcc4b3dfc7a346d8d348798a65f FIREFOX_AURORA_51_BASE
1196bf3032e1bce1fb07a01fd9082a767426c5fb FIREFOX_AURORA_52_BASE
+f80dc9fc34680105b714a49b4704bb843f5f7004 FIREFOX_AURORA_53_BASE
+6583496f169cd8a13c531ed16e98e8bf313eda8e FIREFOX_AURORA_54_BASE
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -8,33 +8,39 @@ metadata:
scopes:
# Note the below scopes are insecure however these get overriden on the server
# side to whatever scopes are set by mozilla-taskcluster.
- queue:*
- docker-worker:*
- scheduler:*
-# Available mustache parameters (see the mozilla-taskcluster source):
+# This file undergoes substitution to create tasks. For on-push tasks, that
+# substitution is done by mozilla-taskcluster. For cron tasks, that substitution
+# is done by `taskcluster/taskgraph/cron/decision.py`. If you change any of the
+# template parameters, please do so in all three places!
#
+# Available template parameters:
+#
+# - now: current time
# - owner: push user (email address)
# - source: URL of this YAML file
# - url: repository URL
# - project: alias for the destination repository (basename of
# the repo url)
# - level: SCM level of the destination repository
# (1 = try, 3 = core)
-# - revision: (short) hg revision of the head of the push
-# - revision_hash: (long) hg revision of the head of the push
+# - revision: hg revision of the head of the push
# - comment: comment of the push
# - pushlog_id: id in the pushlog table of the repository
#
# and functions:
# - as_slugid: convert a label into a slugId
# - from_now: generate a timestamp at a fixed offset from now
+# - shellquote: quote the contents for injection into shell
# The resulting tasks' taskGroupId will be equal to the taskId of the first
# task listed here, which should be the decision task. This gives other tools
# an easy way to determine the ID of the decision task that created a
# particular group.
tasks:
- taskId: '{{#as_slugid}}decision task{{/as_slugid}}'
@@ -50,23 +56,16 @@ tasks:
The task that creates all of the other tasks in the task graph
workerType: "gecko-decision"
provisionerId: "aws-provisioner-v1"
tags:
createdForUser: {{owner}}
- scopes:
- # Bug 1269443: cache scopes, etc. must be listed explicitly
- - "docker-worker:cache:level-{{level}}-*"
- - "docker-worker:cache:tooltool-cache"
- # mozilla-taskcluster will append the appropriate assume:repo:<repo>
- # scope here.
-
routes:
- "index.gecko.v2.{{project}}.latest.firefox.decision"
- "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}"
- "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}"
payload:
env:
# checkout-gecko uses these to check out the source; the inputs
@@ -80,18 +79,18 @@ tasks:
cache:
level-{{level}}-checkouts: /home/worker/checkouts
features:
taskclusterProxy: true
chainOfTrust: true
# Note: This task is built server side without the context or tooling that
- # exist in tree so we must hard code the version
- image: 'taskcluster/decision:0.1.7'
+ # exist in tree so we must hard code the hash
+ image: 'taskcluster/decision:0.1.8@sha256:195d8439c8e90d59311d877bd2a8964849b2e43bfc6c234092618518d8b2891b'
maxRunTime: 1800
# TODO use mozilla-unified for the base repository once the tc-vcs
# tar.gz archives are created or tc-vcs isn't being used.
command:
- /home/worker/bin/run-task
- '--vcs-checkout=/home/worker/checkouts/gecko'
@@ -107,17 +106,16 @@ tasks:
--project='{{project}}'
--message={{#shellquote}}{{{comment}}}{{/shellquote}}
--owner='{{owner}}'
--level='{{level}}'
--base-repository='https://hg.mozilla.org/mozilla-central'
--head-repository='{{{url}}}'
--head-ref='{{revision}}'
--head-rev='{{revision}}'
- --revision-hash='{{revision_hash}}'
artifacts:
'public':
type: 'directory'
path: '/home/worker/artifacts'
expires: '{{#from_now}}364 days{{/from_now}}'
extra:
--- a/AUTHORS
+++ b/AUTHORS
@@ -874,16 +874,17 @@ Roy Yokoyama <yokoyama@netscape.com>
RSA Security, Inc
Russell King <rmk@arm.linux.org.uk>
Rusty Lynch <rusty.lynch@intel.com>
Ryan Cassin <rcassin@supernova.org>
Ryan Flint <rflint@dslr.net>
Ryan Jones <sciguyryan@gmail.com>
Ryan VanderMeulen <ryanvm@gmail.com>
Ryoichi Furukawa <oliver@1000cp.com>
+Sanyam Khurana <Sanyam.Khurana01@gmail.com>
sagdjb@softwareag.com
Samir Gehani <sgehani@netscape.com>
Sammy Ford
Samphan Raruenrom
Samuel Sieb <samuel@sieb.net>
Sarlos Tamas
scole@planetweb.com
Scooter Morris <scootermorris@comcast.net>
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
#
# Modifying this file will now automatically clobber the buildbot machines \o/
#
# Are you updating CLOBBER because you think it's needed for your WebIDL
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
-Bug 1309866 moving files from jar.mn to modules left duplicated files on at least Mac static analysis builds
+Bug 1343682 - backing out a previous version didn't stop the failures from it, so it appears to need a clobber both out and in
--- a/Makefile.in
+++ b/Makefile.in
@@ -91,47 +91,21 @@ config.status js/src/config.status:
# The mach build driver will ensure the backend is up to date for partial tree
# builds. This cleanly avoids most of the pain.
ifndef TEST_MOZBUILD
.PHONY: backend
backend: $(BUILD_BACKEND_FILES)
-# A traditional rule would look like this:
-# backend.%:
-# @echo do stuff
-#
-# But with -j<n>, and multiple items in BUILD_BACKEND_FILES, the command would
-# run multiple times in parallel.
-#
-# "Fortunately", make has some weird semantics for pattern rules: if there are
-# multiple targets in a pattern rule and each of them is matched at most once,
-# the command will only run once. So:
-# backend%RecursiveMakeBackend backend%FasterMakeBackend:
-# @echo do stuff
-# backend: backend.RecursiveMakeBackend backend.FasterMakeBackend
-# would only execute the command once.
-#
-# Credit where due: http://stackoverflow.com/questions/2973445/gnu-makefile-rule-generating-a-few-targets-from-a-single-source-file/3077254#3077254
-$(subst .,%,$(BUILD_BACKEND_FILES)):
- @echo 'Build configuration changed. Regenerating backend.'
- $(PYTHON) config.status
+include $(topsrcdir)/build/rebuild-backend.mk
Makefile: $(BUILD_BACKEND_FILES)
@$(TOUCH) $@
-define build_backend_rule
-$(1)_files := $$(shell cat $(1).in)
-$(1): $$($(1)_files)
-$$($(1)_files):
-
-endef
-$(foreach file,$(BUILD_BACKEND_FILES),$(eval $(call build_backend_rule,$(file))))
-
default:: $(BUILD_BACKEND_FILES)
endif
install_manifests := \
$(addprefix dist/,branding idl include public private sdk xpi-stage) \
_tests \
$(NULL)
# Skip the dist/bin install manifest when using the hybrid
@@ -185,37 +159,38 @@ tup:
# js as standalone because automated builds are building nspr separately and
# that would remove the resulting files.
# Eventually, a standalone js build would just be able to build nspr itself,
# removing the need for the former.
ifdef JS_STANDALONE
NO_REMOVE=1
endif
+# For an artifact build, _tests will already be partly populated, so run
+# this install manifest with NO_REMOVE set in this case.
+ifdef MOZ_ARTIFACT_BUILDS
+install-_tests: NO_REMOVE=1
+endif
+
.PHONY: $(addprefix install-,$(subst /,_,$(install_manifests)))
$(addprefix install-,$(install_manifests)): install-%: $(install_manifest_depends)
ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
@# If we're using the hybrid FasterMake/RecursiveMake backend, we want
@# to ensure the FasterMake end doesn't have install manifests for the
@# same directory, because that would blow up
$(if $(wildcard _build_manifests/install/$(subst /,_,$*)),$(if $(wildcard faster/install_$(subst /,_,$*)*),$(error FasterMake and RecursiveMake ends of the hybrid build system want to handle $*)))
endif
$(addprefix $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$*) ,$(wildcard _build_manifests/install/$(subst /,_,$*)))
# Dummy wrapper rule to allow the faster backend to piggy back
$(addprefix install-,$(subst /,_,$(filter dist/%,$(install_manifests)))): install-dist_%: install-dist/% ;
.PHONY: install-tests
install-tests: install-test-files
-# We no longer run "make install-tests" directly before running tests, but we still
-# want to depend on things like config.status, hence this target.
-.PHONY: run-tests-deps
-run-tests-deps: $(install_manifest_depends)
-
# Force --no-remove, because $objdir/_tests is handled by multiple manifests.
.PHONY: install-test-files
install-test-files:
$(call py_action,process_install_manifest,--no-remove _tests _build_manifests/install/_test_files)
include $(topsrcdir)/build/moz-automation.mk
# dist and _tests should be purged during cleaning. However, we don't want them
@@ -284,23 +259,18 @@ DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_s
else
DUMP_SYMS_BIN ?= $(topsrcdir)/toolkit/crashreporter/tools/win32/dump_syms_vc$(_MSC_VER).exe
endif
# PDB files don't get moved to dist, so we need to scan the whole objdir
MAKE_SYM_STORE_PATH := .
endif
ifeq ($(OS_ARCH),Darwin)
# need to pass arch flags for universal builds
-ifdef UNIVERSAL_BINARY
-MAKE_SYM_STORE_ARGS := -c --vcs-info
-MAKE_SYM_STORE_PATH := $(DIST)/bin $(UNIFY_DIST)/bin
-else
MAKE_SYM_STORE_ARGS := -c -a $(OS_TEST) --vcs-info
MAKE_SYM_STORE_PATH := $(DIST)/bin
-endif
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
endif
ifeq (,$(filter-out Linux SunOS,$(OS_ARCH)))
MAKE_SYM_STORE_ARGS := -c --vcs-info
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
MAKE_SYM_STORE_PATH := $(DIST)/bin
endif
MAKE_SYM_STORE_ARGS += --install-manifest=$(DEPTH)/_build_manifests/install/dist_include,$(DIST)/include
@@ -357,36 +327,16 @@ ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
$(PYTHON) -u $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
endif
endif
.PHONY: update-packaging
update-packaging:
$(MAKE) -C tools/update-packaging
-.PHONY: pretty-package
-pretty-package:
- unset MOZ_SIGN_CMD && $(MAKE) package MOZ_PKG_PRETTYNAMES=1
-
-.PHONY: pretty-package-tests
-pretty-package-tests:
- unset MOZ_SIGN_CMD && $(MAKE) package-tests MOZ_PKG_PRETTYNAMES=1
-
-.PHONY: pretty-l10n-check
-pretty-l10n-check:
- unset MOZ_SIGN_CMD && $(MAKE) l10n-check MOZ_PKG_PRETTYNAMES=1
-
-.PHONY: pretty-update-packaging
-pretty-update-packaging:
- unset MOZ_SIGN_CMD && $(MAKE) -C tools/update-packaging MOZ_PKG_PRETTYNAMES=1
-
-.PHONY: pretty-installer
-pretty-installer:
- unset MOZ_SIGN_CMD && $(MAKE) installer MOZ_PKG_PRETTYNAMES=1
-
#XXX: this is a hack, since we don't want to clobber for MSVC
# PGO support, but we can't do this test in client.mk
ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
# No point in clobbering if PGO has been explicitly disabled.
ifndef NO_PROFILE_GUIDED_OPTIMIZE
maybe_clobber_profiledbuild: clean
else
maybe_clobber_profiledbuild:
--- a/README.txt
+++ b/README.txt
@@ -1,27 +1,27 @@
An explanation of the Mozilla Source Code Directory Structure and links to
project pages with documentation can be found at:
https://developer.mozilla.org/en/Mozilla_Source_Code_Directory_Structure
For information on how to build Mozilla from the source code, see:
- http://developer.mozilla.org/en/docs/Build_Documentation
+ https://developer.mozilla.org/en/docs/Build_Documentation
To have your bug fix / feature added to Mozilla, you should create a patch and
submit it to Bugzilla (https://bugzilla.mozilla.org). Instructions are at:
- http://developer.mozilla.org/en/docs/Creating_a_patch
- http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree
+ https://developer.mozilla.org/en/docs/Creating_a_patch
+ https://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree
If you have a question about developing Mozilla, and can't find the solution
-on http://developer.mozilla.org, you can try asking your question in a
+on https://developer.mozilla.org, you can try asking your question in a
mozilla.* Usenet group, or on IRC at irc.mozilla.org. [The Mozilla news groups
are accessible on Google Groups, or news.mozilla.org with a NNTP reader.]
You can download nightly development builds from the Mozilla FTP server.
Keep in mind that nightly builds, which are used by Mozilla developers for
testing, may be buggy. Firefox nightlies, for example, can be found at:
https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/
- or -
- http://nightly.mozilla.org/
+ https://nightly.mozilla.org/
--- a/accessible/aom/AccessibleNode.cpp
+++ b/accessible/aom/AccessibleNode.cpp
@@ -1,16 +1,19 @@
/* -*- Mode: 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/. */
#include "AccessibleNode.h"
#include "mozilla/dom/AccessibleNodeBinding.h"
#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/DOMStringList.h"
+#include "nsIPersistentProperties2.h"
+#include "nsISimpleEnumerator.h"
#include "Accessible-inl.h"
#include "nsAccessibilityService.h"
#include "DocAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::dom;
@@ -56,13 +59,119 @@ AccessibleNode::GetRole(nsAString& aRole
if (mIntl) {
GetOrCreateAccService()->GetStringRole(mIntl->Role(), aRole);
return;
}
aRole.AssignLiteral("unknown");
}
+void
+AccessibleNode::GetStates(nsTArray<nsString>& aStates)
+{
+ if (mIntl) {
+ if (!mStates) {
+ mStates = GetOrCreateAccService()->GetStringStates(mIntl->State());
+ }
+ aStates = mStates->StringArray();
+ return;
+ }
+
+ aStates.AppendElement(NS_LITERAL_STRING("defunct"));
+}
+
+void
+AccessibleNode::GetAttributes(nsTArray<nsString>& aAttributes)
+{
+ if (!mIntl) {
+ return;
+ }
+
+ nsCOMPtr<nsIPersistentProperties> attrs = mIntl->Attributes();
+
+ nsCOMPtr<nsISimpleEnumerator> props;
+ attrs->Enumerate(getter_AddRefs(props));
+
+ bool hasMore = false;
+ while (NS_SUCCEEDED(props->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> supp;
+ props->GetNext(getter_AddRefs(supp));
+
+ nsCOMPtr<nsIPropertyElement> prop(do_QueryInterface(supp));
+
+ nsAutoCString attr;
+ prop->GetKey(attr);
+ aAttributes.AppendElement(NS_ConvertUTF8toUTF16(attr));
+ }
+}
+
+bool
+AccessibleNode::Is(const Sequence<nsString>& aFlavors)
+{
+ if (!mIntl) {
+ for (const auto& flavor : aFlavors) {
+ if (!flavor.EqualsLiteral("unknown") && !flavor.EqualsLiteral("defunct")) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ nsAutoString role;
+ GetOrCreateAccService()->GetStringRole(mIntl->Role(), role);
+
+ if (!mStates) {
+ mStates = GetOrCreateAccService()->GetStringStates(mIntl->State());
+ }
+
+ for (const auto& flavor : aFlavors) {
+ if (!flavor.Equals(role) && !mStates->Contains(flavor)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+AccessibleNode::Has(const Sequence<nsString>& aAttributes)
+{
+ if (!mIntl) {
+ return false;
+ }
+ nsCOMPtr<nsIPersistentProperties> attrs = mIntl->Attributes();
+ for (const auto& attr : aAttributes) {
+ bool has = false;
+ attrs->Has(NS_ConvertUTF16toUTF8(attr).get(), &has);
+ if (!has) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void
+AccessibleNode::Get(JSContext* aCX, const nsAString& aAttribute,
+ JS::MutableHandle<JS::Value> aValue,
+ ErrorResult& aRv)
+{
+ if (!mIntl) {
+ aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
+ }
+
+ nsCOMPtr<nsIPersistentProperties> attrs = mIntl->Attributes();
+ nsAutoString value;
+ attrs->GetStringProperty(NS_ConvertUTF16toUTF8(aAttribute), value);
+
+ JS::Rooted<JS::Value> jsval(aCX);
+ if (!ToJSValue(aCX, value, &jsval)) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return;
+ }
+
+ aValue.set(jsval);
+}
+
nsINode*
AccessibleNode::GetDOMNode()
{
return mDOMNode;
}
--- a/accessible/aom/AccessibleNode.h
+++ b/accessible/aom/AccessibleNode.h
@@ -3,51 +3,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/. */
#ifndef A11Y_AOM_ACCESSIBLENODE_H
#define A11Y_AOM_ACCESSIBLENODE_H
#include "nsWrapperCache.h"
-#include "mozilla/RefPtr.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/BindingDeclarations.h"
class nsINode;
namespace mozilla {
namespace a11y {
class Accessible;
}
namespace dom {
+class DOMStringList;
struct ParentObject;
class AccessibleNode : public nsISupports,
public nsWrapperCache
{
public:
explicit AccessibleNode(nsINode* aNode);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AccessibleNode);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override final;
virtual dom::ParentObject GetParentObject() const final;
void GetRole(nsAString& aRole);
+ void GetStates(nsTArray<nsString>& aStates);
+ void GetAttributes(nsTArray<nsString>& aAttributes);
nsINode* GetDOMNode();
+ bool Is(const Sequence<nsString>& aFlavors);
+ bool Has(const Sequence<nsString>& aAttributes);
+ void Get(JSContext* cx, const nsAString& aAttribute,
+ JS::MutableHandle<JS::Value> aValue,
+ ErrorResult& aRv);
+
+ a11y::Accessible* Internal() const { return mIntl; }
+
protected:
AccessibleNode(const AccessibleNode& aCopy) = delete;
AccessibleNode& operator=(const AccessibleNode& aCopy) = delete;
virtual ~AccessibleNode();
RefPtr<a11y::Accessible> mIntl;
RefPtr<nsINode> mDOMNode;
+ RefPtr<dom::DOMStringList> mStates;
};
} // dom
} // mozilla
#endif // A11Y_JSAPI_ACCESSIBLENODE
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -8,32 +8,32 @@
#include "Accessible-inl.h"
#include "ApplicationAccessibleWrap.h"
#include "InterfaceInitFuncs.h"
#include "nsAccUtils.h"
#include "mozilla/a11y/PDocAccessible.h"
#include "OuterDocAccessible.h"
#include "ProxyAccessible.h"
+#include "DocAccessibleParent.h"
#include "RootAccessible.h"
#include "TableAccessible.h"
#include "TableCellAccessible.h"
#include "nsMai.h"
#include "nsMaiHyperlink.h"
#include "nsString.h"
#include "nsStateMap.h"
#include "mozilla/a11y/Platform.h"
#include "Relation.h"
#include "RootAccessible.h"
#include "States.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Sprintf.h"
-#include "nsXPCOMStrings.h"
#include "nsComponentManagerUtils.h"
#include "nsIPersistentProperties2.h"
using namespace mozilla;
using namespace mozilla::a11y;
MaiAtkObject::EAvailableAtkSignals MaiAtkObject::gAvailableAtkSignals =
eUnknown;
@@ -608,18 +608,17 @@ getNameCB(AtkObject* aAtkObj)
return aAtkObj->name;
}
static void
MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
{
NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
- if (aAtkObj->name &&
- !strncmp(aAtkObj->name, newNameUTF8.get(), newNameUTF8.Length()))
+ if (aAtkObj->name && !strcmp(aAtkObj->name, newNameUTF8.get()))
return;
// Below we duplicate the functionality of atk_object_set_name(),
// but without calling atk_object_get_name(). Instead of
// atk_object_get_name() we directly access aAtkObj->name. This is because
// atk_object_get_name() would call getNameCB() which would call
// MaybeFireNameChange() (or atk_object_set_name() before this problem was
// fixed) and we would get an infinite recursion.
--- a/accessible/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/atk/nsMaiInterfaceTable.cpp
@@ -322,44 +322,47 @@ getSelectedRowsCB(AtkTable *aTable, gint
}
static gboolean
isColumnSelectedCB(AtkTable *aTable, gint aColIdx)
{
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (accWrap) {
return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
return static_cast<gboolean>(proxy->TableColumnSelected(aColIdx));
}
return FALSE;
}
static gboolean
isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
{
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (accWrap) {
return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
return static_cast<gboolean>(proxy->TableRowSelected(aRowIdx));
}
return FALSE;
}
static gboolean
isCellSelectedCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
{
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (accWrap) {
return static_cast<gboolean>(accWrap->AsTable()->
IsCellSelected(aRowIdx, aColIdx));
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
return static_cast<gboolean>(proxy->TableCellSelected(aRowIdx, aColIdx));
}
return FALSE;
}
}
void
--- a/accessible/atk/nsMaiInterfaceText.cpp
+++ b/accessible/atk/nsMaiInterfaceText.cpp
@@ -495,17 +495,18 @@ getTextSelectionCB(AtkText *aText, gint
return nullptr;
}
text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
*aStartOffset = startOffset;
*aEndOffset = endOffset;
return getTextCB(aText, *aStartOffset, *aEndOffset);
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
nsString data;
proxy->SelectionBoundsAt(aSelectionNum, data, &startOffset, &endOffset);
*aStartOffset = startOffset;
*aEndOffset = endOffset;
NS_ConvertUTF16toUTF8 dataAsUTF8(data);
return (dataAsUTF8.get()) ? g_strdup(dataAsUTF8.get()) : nullptr;
}
@@ -521,17 +522,18 @@ addTextSelectionCB(AtkText *aText,
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (accWrap) {
HyperTextAccessible* text = accWrap->AsHyperText();
if (!text || !text->IsTextRole()) {
return FALSE;
}
return text->AddToSelection(aStartOffset, aEndOffset);
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
return proxy->AddToSelection(aStartOffset, aEndOffset);
}
return FALSE;
}
static gboolean
removeTextSelectionCB(AtkText *aText,
@@ -540,17 +542,18 @@ removeTextSelectionCB(AtkText *aText,
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (accWrap) {
HyperTextAccessible* text = accWrap->AsHyperText();
if (!text || !text->IsTextRole()) {
return FALSE;
}
return text->RemoveFromSelection(aSelectionNum);
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
return proxy->RemoveFromSelection(aSelectionNum);
}
return FALSE;
}
static gboolean
setTextSelectionCB(AtkText *aText, gint aSelectionNum,
@@ -559,17 +562,18 @@ setTextSelectionCB(AtkText *aText, gint
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (accWrap) {
HyperTextAccessible* text = accWrap->AsHyperText();
if (!text || !text->IsTextRole()) {
return FALSE;
}
return text->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
- } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+ }
+ if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
return proxy->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
}
return FALSE;
}
static gboolean
setCaretOffsetCB(AtkText *aText, gint aOffset)
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -179,17 +179,17 @@ static const nsRoleMapEntry sWAIRoleMaps
{ // directory
&nsGkAtoms::directory,
roles::LIST,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eList,
- kNoReqStates
+ states::READONLY
},
{ // document
&nsGkAtoms::document,
roles::DOCUMENT,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -516,44 +516,16 @@ DocManager::CreateDocOrRootAccessible(ns
// the tree. The reorder event is delivered after the document tree is
// constructed because event processing and tree construction are done by
// the same document.
// Note: don't use AccReorderEvent to avoid coalsecense and special reorder
// events processing.
docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
ApplicationAcc());
- if (IPCAccessibilityActive()) {
- nsIDocShell* docShell = aDocument->GetDocShell();
- if (docShell) {
- nsCOMPtr<nsITabChild> tabChild = docShell->GetTabChild();
-
- // XXX We may need to handle the case that we don't have a tab child
- // differently. It may be that this will cause us to fail to notify
- // the parent process about important accessible documents.
- if (tabChild) {
- DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
- docAcc->SetIPCDoc(ipcDoc);
-
- static_cast<TabChild*>(tabChild.get())->
- SendPDocAccessibleConstructor(ipcDoc, nullptr, 0,
-#if defined(XP_WIN)
- AccessibleWrap::GetChildIDFor(docAcc)
-#else
- 0
-#endif
- );
-
-#if defined(XP_WIN)
- IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
- ipcDoc->SendCOMProxy(holder);
-#endif
- }
- }
- }
} else {
parentDocAcc->BindChildDocument(docAcc);
}
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eDocCreate)) {
logging::DocCreate("document creation finished", aDocument);
logging::Stack();
--- a/accessible/base/EventTree.cpp
+++ b/accessible/base/EventTree.cpp
@@ -20,25 +20,24 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// TreeMutation class
EventTree* const TreeMutation::kNoEventTree = reinterpret_cast<EventTree*>(-1);
TreeMutation::TreeMutation(Accessible* aParent, bool aNoEvents) :
mParent(aParent), mStartIdx(UINT32_MAX),
mStateFlagsCopy(mParent->mStateFlags),
- mEventTree(aNoEvents ? kNoEventTree : nullptr),
mQueueEvents(!aNoEvents)
{
#ifdef DEBUG
mIsDone = false;
#endif
#ifdef A11Y_LOG
- if (mEventTree != kNoEventTree && logging::IsEnabled(logging::eEventTree)) {
+ if (mQueueEvents && logging::IsEnabled(logging::eEventTree)) {
logging::MsgBegin("EVENTS_TREE", "reordering tree before");
logging::AccessibleInfo("reordering for", mParent);
Controller()->RootEventTree().Log();
logging::MsgEnd();
if (logging::IsEnabled(logging::eVerbose)) {
logging::Tree("EVENTS_TREE", "Container tree", mParent->Document(),
PrefixLog, static_cast<void*>(this));
@@ -114,17 +113,17 @@ TreeMutation::Done()
mParent->mEmbeddedObjCollector = nullptr;
mParent->mStateFlags |= mStateFlagsCopy & Accessible::eKidsMutating;
#ifdef DEBUG
mIsDone = true;
#endif
#ifdef A11Y_LOG
- if (mEventTree != kNoEventTree && logging::IsEnabled(logging::eEventTree)) {
+ if (mQueueEvents && logging::IsEnabled(logging::eEventTree)) {
logging::MsgBegin("EVENTS_TREE", "reordering tree after");
logging::AccessibleInfo("reordering for", mParent);
Controller()->RootEventTree().Log();
logging::MsgEnd();
}
#endif
}
--- a/accessible/base/EventTree.h
+++ b/accessible/base/EventTree.h
@@ -42,17 +42,16 @@ private:
#ifdef A11Y_LOG
static const char* PrefixLog(void* aData, Accessible*);
#endif
Accessible* mParent;
uint32_t mStartIdx;
uint32_t mStateFlagsCopy;
- EventTree* mEventTree;
/*
* True if mutation events should be queued.
*/
bool mQueueEvents;
#ifdef DEBUG
bool mIsDone;
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -75,17 +75,17 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(N
////////////////////////////////////////////////////////////////////////////////
// NotificationCollector: public
void
NotificationController::Shutdown()
{
if (mObservingState != eNotObservingRefresh &&
- mPresShell->RemoveRefreshObserver(this, Flush_Display)) {
+ mPresShell->RemoveRefreshObserver(this, FlushType::Display)) {
mObservingState = eNotObservingRefresh;
}
// Shutdown handling child documents.
int32_t childDocCount = mHangingChildDocuments.Length();
for (int32_t idx = childDocCount - 1; idx >= 0; idx--) {
if (!mHangingChildDocuments[idx]->IsDefunct())
mHangingChildDocuments[idx]->Shutdown();
@@ -212,49 +212,49 @@ NotificationController::QueueMutationEve
while (prevEvent && prevEvent->GetEventType() == nsIAccessibleEvent::EVENT_REORDER) {
prevEvent = prevEvent->PrevEvent();
}
if (prevEvent && prevEvent->GetEventType() == nsIAccessibleEvent::EVENT_HIDE &&
mutEvent->IsHide()) {
AccHideEvent* prevHide = downcast_accEvent(prevEvent);
AccTextChangeEvent* prevTextChange = prevHide->mTextChangeEvent;
- if (prevTextChange) {
+ if (prevTextChange && prevHide->Parent() == mutEvent->Parent()) {
if (prevHide->mNextSibling == target) {
target->AppendTextTo(prevTextChange->mModifiedText);
+ prevHide->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
} else if (prevHide->mPrevSibling == target) {
nsString temp;
target->AppendTextTo(temp);
uint32_t extraLen = temp.Length();
temp += prevTextChange->mModifiedText;;
prevTextChange->mModifiedText = temp;
prevTextChange->mStart -= extraLen;
+ prevHide->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
}
-
- prevHide->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
}
} else if (prevEvent && mutEvent->IsShow() &&
prevEvent->GetEventType() == nsIAccessibleEvent::EVENT_SHOW) {
AccShowEvent* prevShow = downcast_accEvent(prevEvent);
AccTextChangeEvent* prevTextChange = prevShow->mTextChangeEvent;
- if (prevTextChange) {
+ if (prevTextChange && prevShow->Parent() == target->Parent()) {
int32_t index = target->IndexInParent();
int32_t prevIndex = prevShow->GetAccessible()->IndexInParent();
if (prevIndex + 1 == index) {
target->AppendTextTo(prevTextChange->mModifiedText);
+ prevShow->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
} else if (index + 1 == prevIndex) {
nsString temp;
target->AppendTextTo(temp);
prevTextChange->mStart -= temp.Length();
temp += prevTextChange->mModifiedText;
prevTextChange->mModifiedText = temp;
+ prevShow->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
}
-
- prevShow->mTextChangeEvent.swap(mutEvent->mTextChangeEvent);
}
}
if (!mutEvent->mTextChangeEvent) {
mutEvent->mTextChangeEvent =
new AccTextChangeEvent(container, offset, text, mutEvent->IsShow(),
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
}
@@ -324,30 +324,37 @@ NotificationController::CoalesceMutation
AccReorderEvent* reorder = downcast_accEvent(mMutationMap.GetEvent(parent, EventMap::ReorderEvent));
// We want to make sure that a reorder event comes after any show or
// hide events targeted at the children of its target. We keep the
// invariant that event generation goes up as you are farther in the
// queue, so we want to use the spot of the event with the higher
// generation number, and keep that generation number.
if (reorder && reorder->EventGeneration() < event->EventGeneration()) {
- // There really should be a show or hide event before the first
- // reorder event.
- if (reorder->PrevEvent()) {
- reorder->PrevEvent()->SetNextEvent(reorder->NextEvent());
- } else {
- mFirstMutationEvent = reorder->NextEvent();
+ reorder->SetEventGeneration(event->EventGeneration());
+
+ // It may be true that reorder was before event, and we coalesced
+ // away all the show / hide events between them. In that case
+ // event is already immediately after reorder in the queue and we
+ // do not need to rearrange the list of events.
+ if (event != reorder->NextEvent()) {
+ // There really should be a show or hide event before the first
+ // reorder event.
+ if (reorder->PrevEvent()) {
+ reorder->PrevEvent()->SetNextEvent(reorder->NextEvent());
+ } else {
+ mFirstMutationEvent = reorder->NextEvent();
+ }
+
+ reorder->NextEvent()->SetPrevEvent(reorder->PrevEvent());
+ event->PrevEvent()->SetNextEvent(reorder);
+ reorder->SetPrevEvent(event->PrevEvent());
+ event->SetPrevEvent(reorder);
+ reorder->SetNextEvent(event);
}
-
- reorder->NextEvent()->SetPrevEvent(reorder->PrevEvent());
- event->PrevEvent()->SetNextEvent(reorder);
- reorder->SetPrevEvent(event->PrevEvent());
- event->SetPrevEvent(reorder);
- reorder->SetNextEvent(event);
- reorder->SetEventGeneration(event->EventGeneration());
}
DropMutationEvent(event);
break;
}
acc = parent;
}
} else if (eventType == nsIAccessibleEvent::EVENT_SHOW) {
@@ -432,17 +439,17 @@ NotificationController::ScheduleContentI
}
void
NotificationController::ScheduleProcessing()
{
// If notification flush isn't planed yet start notification flush
// asynchronously (after style and layout).
if (mObservingState == eNotObservingRefresh) {
- if (mPresShell->AddRefreshObserver(this, Flush_Display))
+ if (mPresShell->AddRefreshObserver(this, FlushType::Display))
mObservingState = eRefreshObserving;
}
}
////////////////////////////////////////////////////////////////////////////////
// NotificationCollector: protected
bool
@@ -743,18 +750,21 @@ NotificationController::WillRefresh(mozi
outerDocAcc->RemoveChild(childDoc);
}
// Failed to bind the child document, destroy it.
childDoc->Shutdown();
}
}
-
mHangingChildDocuments.Clear();
+ MOZ_ASSERT(mDocument, "Illicit document shutdown");
+ if (!mDocument) {
+ return;
+ }
// If the document is ready and all its subdocuments are completely loaded
// then process the document load.
if (mDocument->HasLoadState(DocAccessible::eReady) &&
!mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
hangingDocCnt == 0) {
uint32_t childDocCnt = mDocument->ChildDocumentCount(), childDocIdx = 0;
for (; childDocIdx < childDocCnt; childDocIdx++) {
@@ -837,55 +847,59 @@ NotificationController::WillRefresh(mozi
}
ProcessEventQueue();
if (IPCAccessibilityActive()) {
size_t newDocCount = newChildDocs.Length();
for (size_t i = 0; i < newDocCount; i++) {
DocAccessible* childDoc = newChildDocs[i];
+ if (childDoc->IsDefunct()) {
+ continue;
+ }
+
Accessible* parent = childDoc->Parent();
DocAccessibleChild* parentIPCDoc = mDocument->IPCDoc();
+ MOZ_DIAGNOSTIC_ASSERT(parentIPCDoc);
uint64_t id = reinterpret_cast<uintptr_t>(parent->UniqueID());
- MOZ_ASSERT(id);
+ MOZ_DIAGNOSTIC_ASSERT(id);
DocAccessibleChild* ipcDoc = childDoc->IPCDoc();
if (ipcDoc) {
parentIPCDoc->SendBindChildDoc(ipcDoc, id);
continue;
}
ipcDoc = new DocAccessibleChild(childDoc);
childDoc->SetIPCDoc(ipcDoc);
+
+#if defined(XP_WIN)
+ parentIPCDoc->ConstructChildDocInParentProcess(ipcDoc, id,
+ AccessibleWrap::GetChildIDFor(childDoc));
+#else
nsCOMPtr<nsITabChild> tabChild =
do_GetInterface(mDocument->DocumentNode()->GetDocShell());
if (tabChild) {
- MOZ_ASSERT(parentIPCDoc);
static_cast<TabChild*>(tabChild.get())->
- SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id,
-#if defined(XP_WIN)
- AccessibleWrap::GetChildIDFor(childDoc)
-#else
- 0
+ SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id, 0, 0);
+ }
#endif
- );
- }
}
}
mObservingState = eRefreshObserving;
if (!mDocument)
return;
// Stop further processing if there are no new notifications of any kind or
// events and document load is processed.
if (mContentInsertions.Count() == 0 && mNotifications.IsEmpty() &&
mEvents.IsEmpty() && mTextHash.Count() == 0 &&
mHangingChildDocuments.IsEmpty() &&
mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
- mPresShell->RemoveRefreshObserver(this, Flush_Display)) {
+ mPresShell->RemoveRefreshObserver(this, FlushType::Display)) {
mObservingState = eNotObservingRefresh;
}
}
void
NotificationController::EventMap::PutEvent(AccTreeMutationEvent* aEvent)
{
EventType type = GetEventType(aEvent);
--- a/accessible/base/SelectionManager.h
+++ b/accessible/base/SelectionManager.h
@@ -116,17 +116,17 @@ protected:
/**
* Process DOM selection change. Fire selection and caret move events.
*/
void ProcessSelectionChanged(SelData* aSelData);
private:
// Currently focused control.
- nsWeakFrame mCurrCtrlFrame;
+ WeakFrame mCurrCtrlFrame;
int32_t mCaretOffset;
HyperTextAccessible* mAccWithCaret;
};
} // namespace a11y
} // namespace mozilla
#endif
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -13,20 +13,16 @@
#include "gfxFont.h"
#include "nsFontMetrics.h"
#include "nsLayoutUtils.h"
#include "nsContainerFrame.h"
#include "HyperTextAccessible.h"
#include "mozilla/AppUnits.h"
#include "mozilla/gfx/2D.h"
-#if defined(MOZ_WIDGET_GTK)
-#include "gfxPlatformGtk.h" // xxx - for UseFcFontList
-#endif
-
using namespace mozilla;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// TextAttrsMgr
////////////////////////////////////////////////////////////////////////////////
void
@@ -369,20 +365,19 @@ TextAttrsMgr::BGColorTextAttr::
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor,
formattedValue);
}
bool
TextAttrsMgr::BGColorTextAttr::
GetColor(nsIFrame* aFrame, nscolor* aColor)
{
- const nsStyleBackground* styleBackground = aFrame->StyleBackground();
-
- if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
- *aColor = styleBackground->mBackgroundColor;
+ nscolor backgroundColor = aFrame->StyleBackground()->BackgroundColor(aFrame);
+ if (NS_GET_A(backgroundColor) > 0) {
+ *aColor = backgroundColor;
return true;
}
nsContainerFrame *parentFrame = aFrame->GetParent();
if (!parentFrame) {
*aColor = aFrame->PresContext()->DefaultBackgroundColor();
return true;
}
@@ -648,38 +643,24 @@ TextAttrsMgr::FontWeightTextAttr::
// When there doesn't exist a bold font in the family and so the rendering of
// a non-bold font face is changed so that the user sees what looks like a
// bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
// needed on Mac, but it is "safe" to use on all platforms. (For non-Mac
// platforms it always return false.)
if (font->IsSyntheticBold())
return 700;
- bool useFontEntryWeight = true;
-
- // Under Linux, when gfxPangoFontGroup code is used,
- // font->GetStyle()->weight will give the absolute weight requested of the
- // font face. The gfxPangoFontGroup code uses the gfxFontEntry constructor
- // which doesn't initialize the weight field.
-#if defined(MOZ_WIDGET_GTK)
- useFontEntryWeight = gfxPlatformGtk::UseFcFontList();
-#endif
-
- if (useFontEntryWeight) {
- // On Windows, font->GetStyle()->weight will give the same weight as
- // fontEntry->Weight(), the weight of the first font in the font group,
- // which may not be the weight of the font face used to render the
- // characters. On Mac, font->GetStyle()->weight will just give the same
- // number as getComputedStyle(). fontEntry->Weight() will give the weight
- // of the font face used.
- gfxFontEntry *fontEntry = font->GetFontEntry();
- return fontEntry->Weight();
- } else {
- return font->GetStyle()->weight;
- }
+ // On Windows, font->GetStyle()->weight will give the same weight as
+ // fontEntry->Weight(), the weight of the first font in the font group,
+ // which may not be the weight of the font face used to render the
+ // characters. On Mac, font->GetStyle()->weight will just give the same
+ // number as getComputedStyle(). fontEntry->Weight() will give the weight
+ // of the font face used.
+ gfxFontEntry *fontEntry = font->GetFontEntry();
+ return fontEntry->Weight();
}
////////////////////////////////////////////////////////////////////////////////
// AutoGeneratedTextAttr
////////////////////////////////////////////////////////////////////////////////
TextAttrsMgr::AutoGeneratedTextAttr::
AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
Accessible* aAccessible) :
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -58,16 +58,18 @@ if CONFIG['A11Y_LOG']:
UNIFIED_SOURCES += [
'Logging.cpp',
]
LOCAL_INCLUDES += [
'/accessible/generic',
'/accessible/html',
'/accessible/ipc',
+ '/dom/base',
+ '/dom/xul',
]
if CONFIG['OS_ARCH'] == 'WINNT':
LOCAL_INCLUDES += [
'/accessible/ipc/win',
]
else:
LOCAL_INCLUDES += [
--- a/accessible/base/nsAccCache.h
+++ b/accessible/base/nsAccCache.h
@@ -20,26 +20,9 @@ UnbindCacheEntriesFromDocument(
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible && !accessible->IsDefunct());
accessible->Document()->UnbindFromDocument(accessible);
iter.Remove();
}
}
-/**
- * Clear the cache and shutdown the accessibles.
- */
-template <class T>
-static void
-ClearCache(nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
-{
- for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
- T* accessible = iter.Data();
- MOZ_ASSERT(accessible);
- if (accessible && !accessible->IsDefunct()) {
- accessible->Shutdown();
- }
- iter.Remove();
- }
-}
-
#endif
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -56,17 +56,17 @@
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsImageFrame.h"
#include "nsIObserverService.h"
#include "nsLayoutUtils.h"
#include "nsPluginFrame.h"
-#include "nsSVGPathGeometryFrame.h"
+#include "SVGGeometryFrame.h"
#include "nsTreeBodyFrame.h"
#include "nsTreeColumns.h"
#include "nsTreeUtils.h"
#include "nsXBLPrototypeBinding.h"
#include "nsXBLBinding.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/dom/DOMStringList.h"
#include "mozilla/Preferences.h"
@@ -312,26 +312,23 @@ nsAccessibilityService::ListenersChanged
listenerName != nsGkAtoms::onmousedown &&
listenerName != nsGkAtoms::onmouseup) {
continue;
}
nsIDocument* ownerDoc = node->OwnerDoc();
DocAccessible* document = GetExistingDocAccessible(ownerDoc);
- // Always recreate for onclick changes.
- if (document) {
- if (nsCoreUtils::HasClickListener(node)) {
- if (!document->GetAccessible(node)) {
- document->RecreateAccessible(node);
- }
- } else {
- if (document->GetAccessible(node)) {
- document->RecreateAccessible(node);
- }
+ // Create an accessible for a inaccessible element having click event
+ // handler.
+ if (document && !document->HasAccessible(node) &&
+ nsCoreUtils::HasClickListener(node)) {
+ nsIContent* parentEl = node->GetFlattenedTreeParent();
+ if (parentEl) {
+ document->ContentInserted(parentEl, node, node->GetNextSibling());
}
break;
}
}
}
return NS_OK;
}
@@ -401,17 +398,17 @@ nsAccessibilityService::GetRootDocumentA
static StaticAutoPtr<nsTArray<nsCOMPtr<nsIContent> > > sPendingPlugins;
static StaticAutoPtr<nsTArray<nsCOMPtr<nsITimer> > > sPluginTimers;
class PluginTimerCallBack final : public nsITimerCallback
{
~PluginTimerCallBack() {}
public:
- PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
+ explicit PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
NS_DECL_ISUPPORTS
NS_IMETHOD Notify(nsITimer* aTimer) final
{
if (!mContent->IsInUncomposedDoc())
return NS_OK;
@@ -593,16 +590,17 @@ nsAccessibilityService::ContentRemoved(n
if (!child) {
Accessible* container = document->GetContainerAccessible(aChildNode);
a11y::TreeWalker walker(container ? container : document, aChildNode,
a11y::TreeWalker::eWalkCache);
child = walker.Next();
}
if (child) {
+ MOZ_DIAGNOSTIC_ASSERT(child->Parent(), "Unattached accessible from tree");
document->ContentRemoved(child->Parent(), aChildNode);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree))
logging::AccessibleNNode("real container", child->Parent());
#endif
}
}
@@ -746,175 +744,179 @@ nsAccessibilityService::GetStringRole(ui
return;
}
#undef ROLE
}
void
nsAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
- nsISupports **aStringStates)
+ nsISupports** aStringStates)
{
- RefPtr<DOMStringList> stringStates = new DOMStringList();
-
- uint64_t state = nsAccUtils::To64State(aState, aExtraState);
+ RefPtr<DOMStringList> stringStates =
+ GetStringStates(nsAccUtils::To64State(aState, aExtraState));
- // states
- if (state & states::UNAVAILABLE) {
- stringStates->Add(NS_LITERAL_STRING("unavailable"));
- }
- if (state & states::SELECTED) {
- stringStates->Add(NS_LITERAL_STRING("selected"));
- }
- if (state & states::FOCUSED) {
- stringStates->Add(NS_LITERAL_STRING("focused"));
- }
- if (state & states::PRESSED) {
- stringStates->Add(NS_LITERAL_STRING("pressed"));
- }
- if (state & states::CHECKED) {
- stringStates->Add(NS_LITERAL_STRING("checked"));
- }
- if (state & states::MIXED) {
- stringStates->Add(NS_LITERAL_STRING("mixed"));
- }
- if (state & states::READONLY) {
- stringStates->Add(NS_LITERAL_STRING("readonly"));
- }
- if (state & states::HOTTRACKED) {
- stringStates->Add(NS_LITERAL_STRING("hottracked"));
- }
- if (state & states::DEFAULT) {
- stringStates->Add(NS_LITERAL_STRING("default"));
- }
- if (state & states::EXPANDED) {
- stringStates->Add(NS_LITERAL_STRING("expanded"));
- }
- if (state & states::COLLAPSED) {
- stringStates->Add(NS_LITERAL_STRING("collapsed"));
- }
- if (state & states::BUSY) {
- stringStates->Add(NS_LITERAL_STRING("busy"));
- }
- if (state & states::FLOATING) {
- stringStates->Add(NS_LITERAL_STRING("floating"));
- }
- if (state & states::ANIMATED) {
- stringStates->Add(NS_LITERAL_STRING("animated"));
- }
- if (state & states::INVISIBLE) {
- stringStates->Add(NS_LITERAL_STRING("invisible"));
- }
- if (state & states::OFFSCREEN) {
- stringStates->Add(NS_LITERAL_STRING("offscreen"));
- }
- if (state & states::SIZEABLE) {
- stringStates->Add(NS_LITERAL_STRING("sizeable"));
- }
- if (state & states::MOVEABLE) {
- stringStates->Add(NS_LITERAL_STRING("moveable"));
- }
- if (state & states::SELFVOICING) {
- stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
- }
- if (state & states::FOCUSABLE) {
- stringStates->Add(NS_LITERAL_STRING("focusable"));
- }
- if (state & states::SELECTABLE) {
- stringStates->Add(NS_LITERAL_STRING("selectable"));
- }
- if (state & states::LINKED) {
- stringStates->Add(NS_LITERAL_STRING("linked"));
- }
- if (state & states::TRAVERSED) {
- stringStates->Add(NS_LITERAL_STRING("traversed"));
- }
- if (state & states::MULTISELECTABLE) {
- stringStates->Add(NS_LITERAL_STRING("multiselectable"));
- }
- if (state & states::EXTSELECTABLE) {
- stringStates->Add(NS_LITERAL_STRING("extselectable"));
- }
- if (state & states::PROTECTED) {
- stringStates->Add(NS_LITERAL_STRING("protected"));
- }
- if (state & states::HASPOPUP) {
- stringStates->Add(NS_LITERAL_STRING("haspopup"));
- }
- if (state & states::REQUIRED) {
- stringStates->Add(NS_LITERAL_STRING("required"));
- }
- if (state & states::ALERT) {
- stringStates->Add(NS_LITERAL_STRING("alert"));
- }
- if (state & states::INVALID) {
- stringStates->Add(NS_LITERAL_STRING("invalid"));
- }
- if (state & states::CHECKABLE) {
- stringStates->Add(NS_LITERAL_STRING("checkable"));
- }
-
- // extraStates
- if (state & states::SUPPORTS_AUTOCOMPLETION) {
- stringStates->Add(NS_LITERAL_STRING("autocompletion"));
- }
- if (state & states::DEFUNCT) {
- stringStates->Add(NS_LITERAL_STRING("defunct"));
- }
- if (state & states::SELECTABLE_TEXT) {
- stringStates->Add(NS_LITERAL_STRING("selectable text"));
- }
- if (state & states::EDITABLE) {
- stringStates->Add(NS_LITERAL_STRING("editable"));
- }
- if (state & states::ACTIVE) {
- stringStates->Add(NS_LITERAL_STRING("active"));
- }
- if (state & states::MODAL) {
- stringStates->Add(NS_LITERAL_STRING("modal"));
- }
- if (state & states::MULTI_LINE) {
- stringStates->Add(NS_LITERAL_STRING("multi line"));
- }
- if (state & states::HORIZONTAL) {
- stringStates->Add(NS_LITERAL_STRING("horizontal"));
- }
- if (state & states::OPAQUE1) {
- stringStates->Add(NS_LITERAL_STRING("opaque"));
- }
- if (state & states::SINGLE_LINE) {
- stringStates->Add(NS_LITERAL_STRING("single line"));
- }
- if (state & states::TRANSIENT) {
- stringStates->Add(NS_LITERAL_STRING("transient"));
- }
- if (state & states::VERTICAL) {
- stringStates->Add(NS_LITERAL_STRING("vertical"));
- }
- if (state & states::STALE) {
- stringStates->Add(NS_LITERAL_STRING("stale"));
- }
- if (state & states::ENABLED) {
- stringStates->Add(NS_LITERAL_STRING("enabled"));
- }
- if (state & states::SENSITIVE) {
- stringStates->Add(NS_LITERAL_STRING("sensitive"));
- }
- if (state & states::EXPANDABLE) {
- stringStates->Add(NS_LITERAL_STRING("expandable"));
- }
-
- //unknown states
+ // unknown state
if (!stringStates->Length()) {
stringStates->Add(NS_LITERAL_STRING("unknown"));
}
stringStates.forget(aStringStates);
}
+already_AddRefed<DOMStringList>
+nsAccessibilityService::GetStringStates(uint64_t aStates) const
+{
+ RefPtr<DOMStringList> stringStates = new DOMStringList();
+
+ if (aStates & states::UNAVAILABLE) {
+ stringStates->Add(NS_LITERAL_STRING("unavailable"));
+ }
+ if (aStates & states::SELECTED) {
+ stringStates->Add(NS_LITERAL_STRING("selected"));
+ }
+ if (aStates & states::FOCUSED) {
+ stringStates->Add(NS_LITERAL_STRING("focused"));
+ }
+ if (aStates & states::PRESSED) {
+ stringStates->Add(NS_LITERAL_STRING("pressed"));
+ }
+ if (aStates & states::CHECKED) {
+ stringStates->Add(NS_LITERAL_STRING("checked"));
+ }
+ if (aStates & states::MIXED) {
+ stringStates->Add(NS_LITERAL_STRING("mixed"));
+ }
+ if (aStates & states::READONLY) {
+ stringStates->Add(NS_LITERAL_STRING("readonly"));
+ }
+ if (aStates & states::HOTTRACKED) {
+ stringStates->Add(NS_LITERAL_STRING("hottracked"));
+ }
+ if (aStates & states::DEFAULT) {
+ stringStates->Add(NS_LITERAL_STRING("default"));
+ }
+ if (aStates & states::EXPANDED) {
+ stringStates->Add(NS_LITERAL_STRING("expanded"));
+ }
+ if (aStates & states::COLLAPSED) {
+ stringStates->Add(NS_LITERAL_STRING("collapsed"));
+ }
+ if (aStates & states::BUSY) {
+ stringStates->Add(NS_LITERAL_STRING("busy"));
+ }
+ if (aStates & states::FLOATING) {
+ stringStates->Add(NS_LITERAL_STRING("floating"));
+ }
+ if (aStates & states::ANIMATED) {
+ stringStates->Add(NS_LITERAL_STRING("animated"));
+ }
+ if (aStates & states::INVISIBLE) {
+ stringStates->Add(NS_LITERAL_STRING("invisible"));
+ }
+ if (aStates & states::OFFSCREEN) {
+ stringStates->Add(NS_LITERAL_STRING("offscreen"));
+ }
+ if (aStates & states::SIZEABLE) {
+ stringStates->Add(NS_LITERAL_STRING("sizeable"));
+ }
+ if (aStates & states::MOVEABLE) {
+ stringStates->Add(NS_LITERAL_STRING("moveable"));
+ }
+ if (aStates & states::SELFVOICING) {
+ stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
+ }
+ if (aStates & states::FOCUSABLE) {
+ stringStates->Add(NS_LITERAL_STRING("focusable"));
+ }
+ if (aStates & states::SELECTABLE) {
+ stringStates->Add(NS_LITERAL_STRING("selectable"));
+ }
+ if (aStates & states::LINKED) {
+ stringStates->Add(NS_LITERAL_STRING("linked"));
+ }
+ if (aStates & states::TRAVERSED) {
+ stringStates->Add(NS_LITERAL_STRING("traversed"));
+ }
+ if (aStates & states::MULTISELECTABLE) {
+ stringStates->Add(NS_LITERAL_STRING("multiselectable"));
+ }
+ if (aStates & states::EXTSELECTABLE) {
+ stringStates->Add(NS_LITERAL_STRING("extselectable"));
+ }
+ if (aStates & states::PROTECTED) {
+ stringStates->Add(NS_LITERAL_STRING("protected"));
+ }
+ if (aStates & states::HASPOPUP) {
+ stringStates->Add(NS_LITERAL_STRING("haspopup"));
+ }
+ if (aStates & states::REQUIRED) {
+ stringStates->Add(NS_LITERAL_STRING("required"));
+ }
+ if (aStates & states::ALERT) {
+ stringStates->Add(NS_LITERAL_STRING("alert"));
+ }
+ if (aStates & states::INVALID) {
+ stringStates->Add(NS_LITERAL_STRING("invalid"));
+ }
+ if (aStates & states::CHECKABLE) {
+ stringStates->Add(NS_LITERAL_STRING("checkable"));
+ }
+ if (aStates & states::SUPPORTS_AUTOCOMPLETION) {
+ stringStates->Add(NS_LITERAL_STRING("autocompletion"));
+ }
+ if (aStates & states::DEFUNCT) {
+ stringStates->Add(NS_LITERAL_STRING("defunct"));
+ }
+ if (aStates & states::SELECTABLE_TEXT) {
+ stringStates->Add(NS_LITERAL_STRING("selectable text"));
+ }
+ if (aStates & states::EDITABLE) {
+ stringStates->Add(NS_LITERAL_STRING("editable"));
+ }
+ if (aStates & states::ACTIVE) {
+ stringStates->Add(NS_LITERAL_STRING("active"));
+ }
+ if (aStates & states::MODAL) {
+ stringStates->Add(NS_LITERAL_STRING("modal"));
+ }
+ if (aStates & states::MULTI_LINE) {
+ stringStates->Add(NS_LITERAL_STRING("multi line"));
+ }
+ if (aStates & states::HORIZONTAL) {
+ stringStates->Add(NS_LITERAL_STRING("horizontal"));
+ }
+ if (aStates & states::OPAQUE1) {
+ stringStates->Add(NS_LITERAL_STRING("opaque"));
+ }
+ if (aStates & states::SINGLE_LINE) {
+ stringStates->Add(NS_LITERAL_STRING("single line"));
+ }
+ if (aStates & states::TRANSIENT) {
+ stringStates->Add(NS_LITERAL_STRING("transient"));
+ }
+ if (aStates & states::VERTICAL) {
+ stringStates->Add(NS_LITERAL_STRING("vertical"));
+ }
+ if (aStates & states::STALE) {
+ stringStates->Add(NS_LITERAL_STRING("stale"));
+ }
+ if (aStates & states::ENABLED) {
+ stringStates->Add(NS_LITERAL_STRING("enabled"));
+ }
+ if (aStates & states::SENSITIVE) {
+ stringStates->Add(NS_LITERAL_STRING("sensitive"));
+ }
+ if (aStates & states::EXPANDABLE) {
+ stringStates->Add(NS_LITERAL_STRING("expandable"));
+ }
+
+ return stringStates.forget();
+}
+
void
nsAccessibilityService::GetStringEventType(uint32_t aEventType,
nsAString& aString)
{
NS_ASSERTION(nsIAccessibleEvent::EVENT_LAST_ENTRY == ArrayLength(kEventTypeNames),
"nsIAccessibleEvent constants are out of sync to kEventTypeNames");
if (aEventType >= ArrayLength(kEventTypeNames)) {
@@ -1164,18 +1166,18 @@ nsAccessibilityService::CreateAccessible
frameType == nsGkAtoms::scrollFrame) {
newAcc = new XULTabpanelAccessible(content, document);
}
}
}
if (!newAcc) {
if (content->IsSVGElement()) {
- nsSVGPathGeometryFrame* pathGeometryFrame = do_QueryFrame(frame);
- if (pathGeometryFrame) {
+ SVGGeometryFrame* geometryFrame = do_QueryFrame(frame);
+ if (geometryFrame) {
// A graphic elements: rect, circle, ellipse, line, path, polygon,
// polyline and image. A 'use' and 'text' graphic elements require
// special support.
newAcc = new EnumRoleAccessible<roles::GRAPHIC>(content, document);
} else if (content->IsSVGElement(nsGkAtoms::svg)) {
newAcc = new EnumRoleAccessible<roles::DIAGRAM>(content, document);
}
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -19,16 +19,21 @@
class nsImageFrame;
class nsIArray;
class nsIPersistentProperties;
class nsPluginFrame;
class nsITreeView;
namespace mozilla {
+
+namespace dom {
+ class DOMStringList;
+}
+
namespace a11y {
class ApplicationAccessible;
class xpcAccessibleApplication;
/**
* Return focus manager.
*/
@@ -103,16 +108,18 @@ public:
/**
* Get a string equivalent for an accessilbe role value.
*/
void GetStringRole(uint32_t aRole, nsAString& aString);
/**
* Get a string equivalent for an accessible state/extra state.
*/
+ already_AddRefed<mozilla::dom::DOMStringList>
+ GetStringStates(uint64_t aStates) const;
void GetStringStates(uint32_t aState, uint32_t aExtraState,
nsISupports **aStringStates);
/**
* Get a string equivalent for an accessible event value.
*/
void GetStringEventType(uint32_t aEventType, nsAString& aString);
@@ -331,22 +338,17 @@ nsAccessibilityService* GetOrCreateAccSe
void MaybeShutdownAccService(uint32_t aFormerConsumer);
/**
* Return true if we're in a content process and not B2G.
*/
inline bool
IPCAccessibilityActive()
{
-#ifdef MOZ_B2G
- return false;
-#else
- return XRE_IsContentProcess() &&
- mozilla::Preferences::GetBool("accessibility.ipc_architecture.enabled", true);
-#endif
+ return XRE_IsContentProcess();
}
/**
* Map nsIAccessibleEvents constants to strings. Used by
* nsAccessibilityService::GetStringEventType() method.
*/
static const char kEventTypeNames[][40] = {
"unknown", //
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -9,26 +9,28 @@
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLElement.h"
#include "nsRange.h"
#include "nsIBoxObject.h"
-#include "nsIDOMXULElement.h"
+#include "nsXULElement.h"
+#include "mozilla/dom/BoxObject.h"
#include "nsIDocShell.h"
#include "nsIObserverService.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIScrollableFrame.h"
#include "nsISelectionPrivate.h"
#include "nsISelectionController.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/dom/TouchEvent.h"
+#include "mozilla/ErrorResult.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TouchEvents.h"
#include "nsView.h"
#include "nsGkAtoms.h"
#include "nsComponentManagerUtils.h"
@@ -92,28 +94,29 @@ nsCoreUtils::DispatchClickEvent(nsITreeB
// Calculate x and y coordinates.
int32_t x = 0, y = 0, width = 0, height = 0;
nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
aPseudoElt,
&x, &y, &width, &height);
if (NS_FAILED(rv))
return;
- nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
- nsCOMPtr<nsIBoxObject> tcBoxObj;
- tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj));
+ nsCOMPtr<nsIContent> tcXULElm(do_QueryInterface(tcElm));
+ IgnoredErrorResult ignored;
+ nsCOMPtr<nsIBoxObject> tcBoxObj =
+ nsXULElement::FromContent(tcXULElm)->GetBoxObject(ignored);
int32_t tcX = 0;
tcBoxObj->GetX(&tcX);
int32_t tcY = 0;
tcBoxObj->GetY(&tcY);
// Dispatch mouse events.
- nsWeakFrame tcFrame = tcContent->GetPrimaryFrame();
+ AutoWeakFrame tcFrame = tcContent->GetPrimaryFrame();
nsIFrame* rootFrame = presShell->GetRootFrame();
nsPoint offset;
nsIWidget *rootWidget =
rootFrame->GetView()->GetNearestWidget(&offset);
RefPtr<nsPresContext> presContext = presShell->GetPresContext();
@@ -484,42 +487,41 @@ nsCoreUtils::GetLanguageFor(nsIContent *
walkUp = walkUp->GetParent();
}
already_AddRefed<nsIBoxObject>
nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
{
nsCOMPtr<nsIDOMElement> tcElm;
aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
- nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
+ nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
+ RefPtr<nsXULElement> tcXULElm = nsXULElement::FromContentOrNull(tcContent);
if (!tcXULElm)
return nullptr;
- nsCOMPtr<nsIBoxObject> boxObj;
- tcXULElm->GetBoxObject(getter_AddRefs(boxObj));
- return boxObj.forget();
+ IgnoredErrorResult ignored;
+ return tcXULElm->GetBoxObject(ignored);
}
already_AddRefed<nsITreeBoxObject>
nsCoreUtils::GetTreeBoxObject(nsIContent *aContent)
{
// Find DOMNode's parents recursively until reach the <tree> tag
nsIContent* currentContent = aContent;
while (currentContent) {
if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree,
kNameSpaceID_XUL)) {
// We will get the nsITreeBoxObject from the tree node
- nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentContent));
- if (xulElement) {
- nsCOMPtr<nsIBoxObject> box;
- xulElement->GetBoxObject(getter_AddRefs(box));
- nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
- if (treeBox)
- return treeBox.forget();
- }
+ RefPtr<nsXULElement> xulElement =
+ nsXULElement::FromContent(currentContent);
+ IgnoredErrorResult ignored;
+ nsCOMPtr<nsIBoxObject> box = xulElement->GetBoxObject(ignored);
+ nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
+ if (treeBox)
+ return treeBox.forget();
}
currentContent = currentContent->GetFlattenedTreeParent();
}
return nullptr;
}
already_AddRefed<nsITreeColumn>
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -88,17 +88,23 @@
using namespace mozilla;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// Accessible: nsISupports and cycle collection
-NS_IMPL_CYCLE_COLLECTION(Accessible, mContent)
+NS_IMPL_CYCLE_COLLECTION_CLASS(Accessible)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Accessible)
+ tmp->Shutdown();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Accessible)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent, mDoc)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Accessible)
if (aIID.Equals(NS_GET_IID(Accessible)))
foundInterface = this;
else
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, Accessible)
NS_INTERFACE_MAP_END
@@ -1819,17 +1825,17 @@ Accessible::DispatchClickEvent(nsIConten
nsCOMPtr<nsIPresShell> presShell = mDoc->PresShell();
// Scroll into view.
presShell->ScrollContentIntoView(aContent,
nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis(),
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
- nsWeakFrame frame = aContent->GetPrimaryFrame();
+ AutoWeakFrame frame = aContent->GetPrimaryFrame();
if (!frame)
return;
// Compute x and y coordinates.
nsPoint point;
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(point);
if (!widget)
return;
@@ -2120,48 +2126,53 @@ Accessible::InsertChildAt(uint32_t aInde
aChild->BindToParent(this, aIndex);
return true;
}
bool
Accessible::RemoveChild(Accessible* aChild)
{
- if (!aChild)
- return false;
-
- if (aChild->mParent != this || aChild->mIndexInParent == -1)
- return false;
-
- MOZ_ASSERT((mStateFlags & eKidsMutating) || aChild->IsDefunct() || aChild->IsDoc(),
- "Illicit children change");
+ MOZ_DIAGNOSTIC_ASSERT(aChild, "No child was given");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mParent, "No parent");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mParent == this, "Wrong parent");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
+ MOZ_DIAGNOSTIC_ASSERT((mStateFlags & eKidsMutating) || aChild->IsDefunct() || aChild->IsDoc(),
+ "Illicit children change");
int32_t index = static_cast<uint32_t>(aChild->mIndexInParent);
- MOZ_ASSERT(mChildren.SafeElementAt(index) == aChild,
- "A wrong child index");
+ if (mChildren.SafeElementAt(index) != aChild) {
+ MOZ_ASSERT_UNREACHABLE("A wrong child index");
+ index = mChildren.IndexOf(aChild);
+ if (index == -1) {
+ MOZ_ASSERT_UNREACHABLE("No child was found");
+ return false;
+ }
+ }
aChild->UnbindFromParent();
mChildren.RemoveElementAt(index);
for (uint32_t idx = index; idx < mChildren.Length(); idx++) {
mChildren[idx]->mIndexInParent = idx;
}
return true;
}
void
Accessible::MoveChild(uint32_t aNewIndex, Accessible* aChild)
{
- MOZ_ASSERT(aChild, "No child was given");
- MOZ_ASSERT(aChild->mParent == this, "A child from different subtree was given");
- MOZ_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
- MOZ_ASSERT(static_cast<uint32_t>(aChild->mIndexInParent) != aNewIndex,
+ MOZ_DIAGNOSTIC_ASSERT(aChild, "No child was given");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mParent == this, "A child from different subtree was given");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
+ MOZ_DIAGNOSTIC_ASSERT(aChild->mParent->GetChildAt(aChild->mIndexInParent) == aChild, "Wrong index in parent");
+ MOZ_DIAGNOSTIC_ASSERT(static_cast<uint32_t>(aChild->mIndexInParent) != aNewIndex,
"No move, same index");
- MOZ_ASSERT(aNewIndex <= mChildren.Length(), "Wrong new index was given");
+ MOZ_DIAGNOSTIC_ASSERT(aNewIndex <= mChildren.Length(), "Wrong new index was given");
RefPtr<AccHideEvent> hideEvent = new AccHideEvent(aChild, false);
if (mDoc->Controller()->QueueMutationEvent(hideEvent)) {
aChild->SetHideEventTarget(true);
}
mEmbeddedObjCollector = nullptr;
mChildren.RemoveElementAt(aChild->mIndexInParent);
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -1133,17 +1133,17 @@ protected:
/**
* Return group info.
*/
AccGroupInfo* GetGroupInfo();
// Data Members
nsCOMPtr<nsIContent> mContent;
- DocAccessible* mDoc;
+ RefPtr<DocAccessible> mDoc;
Accessible* mParent;
nsTArray<Accessible*> mChildren;
int32_t mIndexInParent;
static const uint8_t kStateFlagsBits = 13;
static const uint8_t kContextFlagsBits = 3;
static const uint8_t kTypeBits = 6;
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -41,16 +41,17 @@
#include "nsIScrollableFrame.h"
#include "nsUnicharUtils.h"
#include "nsIURI.h"
#include "nsIWebNavigation.h"
#include "nsFocusManager.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/EventStates.h"
+#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/DocumentType.h"
#include "mozilla/dom/Element.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#endif
using namespace mozilla;
@@ -74,28 +75,34 @@ static nsIAtom** kRelationAttrs[] =
static const uint32_t kRelationAttrsLen = ArrayLength(kRelationAttrs);
////////////////////////////////////////////////////////////////////////////////
// Constructor/desctructor
DocAccessible::
DocAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell) :
- HyperTextAccessibleWrap(nullptr, this),
+ // XXX don't pass a document to the Accessible constructor so that we don't
+ // set mDoc until our vtable is fully setup. If we set mDoc before setting
+ // up the vtable we will call Accessible::AddRef() but not the overrides of
+ // it for subclasses. It is important to call those overrides to avoid
+ // confusing leak checking machinary.
+ HyperTextAccessibleWrap(nullptr, nullptr),
// XXX aaronl should we use an algorithm for the initial cache size?
mAccessibleCache(kDefaultCacheLength),
mNodeToAccessibleMap(kDefaultCacheLength),
mDocumentNode(aDocument),
mScrollPositionChangedTicks(0),
mLoadState(eTreeConstructionPending), mDocFlags(0), mLoadEventType(0),
mVirtualCursor(nullptr),
mPresShell(aPresShell), mIPCDoc(nullptr)
{
mGenericTypes |= eDocument;
mStateFlags |= eNotNodeMapEntry;
+ mDoc = this;
MOZ_ASSERT(mPresShell, "should have been given a pres shell");
mPresShell->SetDocAccessible(this);
// If this is a XUL Document, it should not implement nsHyperText
if (mDocumentNode && mDocumentNode->IsXULDocument())
mGenericTypes &= ~eHyperText;
}
@@ -471,17 +478,27 @@ DocAccessible::Shutdown()
mVirtualCursor = nullptr;
}
mPresShell->SetDocAccessible(nullptr);
mPresShell = nullptr; // Avoid reentrancy
mDependentIDsHash.Clear();
mNodeToAccessibleMap.Clear();
- ClearCache(mAccessibleCache);
+
+ for (auto iter = mAccessibleCache.Iter(); !iter.Done(); iter.Next()) {
+ Accessible* accessible = iter.Data();
+ MOZ_ASSERT(accessible);
+ if (accessible && !accessible->IsDefunct()) {
+ // Unlink parent to avoid its cleaning overhead in shutdown.
+ accessible->mParent = nullptr;
+ accessible->Shutdown();
+ }
+ iter.Remove();
+ }
HyperTextAccessibleWrap::Shutdown();
GetAccService()->NotifyOfDocumentShutdown(this, kungFuDeathGripDoc);
}
nsIFrame*
DocAccessible::GetFrame() const
@@ -1455,18 +1472,35 @@ DocAccessible::NotifyOfLoading(bool aIsR
RefPtr<AccEvent> stateEvent =
new AccStateChangeEvent(this, states::BUSY, true);
FireDelayedEvent(stateEvent);
}
void
DocAccessible::DoInitialUpdate()
{
- if (nsCoreUtils::IsTabDocument(mDocumentNode))
+ if (nsCoreUtils::IsTabDocument(mDocumentNode)) {
mDocFlags |= eTabDocument;
+ if (IPCAccessibilityActive()) {
+ nsIDocShell* docShell = mDocumentNode->GetDocShell();
+ if (RefPtr<dom::TabChild> tabChild = dom::TabChild::GetFrom(docShell)) {
+ DocAccessibleChild* ipcDoc = new DocAccessibleChild(this);
+ SetIPCDoc(ipcDoc);
+
+#if defined(XP_WIN)
+ IAccessibleHolder holder(CreateHolderFromAccessible(this));
+ int32_t childID = AccessibleWrap::GetChildIDFor(this);
+#else
+ int32_t holder = 0, childID = 0;
+#endif
+ tabChild->SendPDocAccessibleConstructor(ipcDoc, nullptr, 0, childID,
+ holder);
+ }
+ }
+ }
mLoadState |= eTreeConstructed;
// Set up a root element and ARIA role mapping.
UpdateRootElIfNeeded();
// Build initial tree.
CacheChildrenInSubtree(this);
@@ -2058,21 +2092,23 @@ DocAccessible::DoARIAOwnsRelocation(Acce
TreeMutation imut(aOwner);
aOwner->InsertChildAt(insertIdx, child);
imut.AfterInsertion(child);
imut.Done();
child->SetRelocated(true);
children->InsertElementAt(arrayIdx, child);
+ // Create subtree before adjusting the insertion index, since subtree
+ // creation may alter children in the container.
+ CreateSubtree(child);
+ FireEventsOnInsertion(aOwner);
+
insertIdx = child->IndexInParent() + 1;
arrayIdx++;
-
- CreateSubtree(child);
- FireEventsOnInsertion(aOwner);
}
}
continue;
}
#ifdef A11Y_LOG
logging::TreeInfo("aria owns traversal", logging::eVerbose,
"candidate", child, nullptr);
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -347,17 +347,17 @@ public:
void ContentRemoved(Accessible* aContainer, nsIContent* aChildNode)
{
// Update the whole tree of this document accessible when the container is
// null (document element is removed).
UpdateTreeOnRemoval((aContainer ? aContainer : this), aChildNode);
}
void ContentRemoved(nsIContent* aContainerNode, nsIContent* aChildNode)
{
- ContentRemoved(GetAccessibleOrContainer(aContainerNode), aChildNode);
+ ContentRemoved(AccessibleOrTrueContainer(aContainerNode), aChildNode);
}
/**
* Updates accessible tree when rendered text is changed.
*/
void UpdateText(nsIContent* aTextNode);
/**
--- a/accessible/generic/OuterDocAccessible.cpp
+++ b/accessible/generic/OuterDocAccessible.cpp
@@ -25,16 +25,22 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
OuterDocAccessible::
OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
mType = eOuterDocType;
+#ifdef XP_WIN
+ if (DocAccessibleParent* remoteDoc = RemoteChildDoc()) {
+ remoteDoc->SendParentCOMProxy();
+ }
+#endif
+
// Request document accessible for the content document to make sure it's
// created. It will appended to outerdoc accessible children asynchronously.
nsIDocument* outerDoc = mContent->GetUncomposedDoc();
if (outerDoc) {
nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent);
if (innerDoc)
GetAccService()->GetDocAccessible(innerDoc);
}
@@ -202,17 +208,17 @@ OuterDocAccessible::GetChildAt(uint32_t
if (!remoteChild) {
return nullptr;
}
return WrapperFor(remoteChild);
}
#endif // defined(XP_WIN)
-ProxyAccessible*
+DocAccessibleParent*
OuterDocAccessible::RemoteChildDoc() const
{
dom::TabParent* tab = dom::TabParent::GetFrom(GetContent());
if (!tab)
return nullptr;
return tab->GetTopLevelDocAccessible();
}
--- a/accessible/generic/OuterDocAccessible.h
+++ b/accessible/generic/OuterDocAccessible.h
@@ -5,17 +5,17 @@
#ifndef MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
#define MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_
#include "AccessibleWrap.h"
namespace mozilla {
namespace a11y {
-class ProxyAccessible;
+class DocAccessibleParent;
/**
* Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
*
* In these variable names, "outer" relates to the OuterDocAccessible as
* opposed to the DocAccessibleWrap which is "inner". The outer node is
* a something like tags listed above, whereas the inner node corresponds to
* the inner document root.
@@ -23,17 +23,17 @@ class ProxyAccessible;
class OuterDocAccessible final : public AccessibleWrap
{
public:
OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc);
NS_DECL_ISUPPORTS_INHERITED
- ProxyAccessible* RemoteChildDoc() const;
+ DocAccessibleParent* RemoteChildDoc() const;
// Accessible
virtual void Shutdown() override;
virtual mozilla::a11y::role NativeRole() override;
virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
EWhichChildAtPoint aWhichChild) override;
virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
--- a/accessible/html/HTMLListAccessible.h
+++ b/accessible/html/HTMLListAccessible.h
@@ -58,17 +58,17 @@ public:
// HTMLLIAccessible
HTMLListBulletAccessible* Bullet() const { return mBullet; }
void UpdateBullet(bool aHasBullet);
protected:
virtual ~HTMLLIAccessible() { }
private:
- RefPtr<HTMLListBulletAccessible> mBullet;
+ HTMLListBulletAccessible* mBullet;
};
/**
* Used for bullet of HTML list item element (for example, HTML li).
*/
class HTMLListBulletAccessible : public LeafAccessible
{
--- a/accessible/html/HTMLTableAccessible.cpp
+++ b/accessible/html/HTMLTableAccessible.cpp
@@ -1070,17 +1070,17 @@ HTMLTableAccessible::IsProbablyLayoutTab
uint32_t childCount = ChildCount();
nscolor rowColor = 0;
nscolor prevRowColor;
for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
Accessible* child = GetChildAt(childIdx);
if (child->Role() == roles::ROW) {
prevRowColor = rowColor;
nsIFrame* rowFrame = child->GetFrame();
- rowColor = rowFrame->StyleBackground()->mBackgroundColor;
+ rowColor = rowFrame->StyleBackground()->BackgroundColor(rowFrame);
if (childIdx > 0 && prevRowColor != rowColor)
RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
}
}
// Check for many rows
const uint32_t kMaxLayoutRows = 20;
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/IGeckoCustom.idl
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "objidl.idl";
+import "oaidl.idl";
+
+[object, uuid(7510360f-cdae-4de9-88c8-d167eda62afc)]
+interface IGeckoCustom : IUnknown
+{
+ [propget] HRESULT ID([out, retval] unsigned __int64* aID);
+ [propget] HRESULT anchorCount([out, retval] long* aCount);
+ [propget] HRESULT DOMNodeID([out, retval] BSTR* aID);
+ [propget] HRESULT minimumIncrement([out, retval] double* aIncrement);
+ [propget] HRESULT mozState([out, retval] unsigned __int64* aState);
+}
+
+
+[
+ uuid(55769d85-f830-4d76-9e39-3670914a28f7),
+ helpstring("private custom gecko interfaces")
+]
+library IGeckoCustom
+{
+ interface IGeckoCustom;
+};
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/Makefile.in
@@ -0,0 +1,33 @@
+# 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/.
+
+GARBAGE += $(MIDL_GENERATED_FILES) done_gen
+
+MIDL_GENERATED_FILES = \
+ dlldata.c \
+ IGeckoCustom.h \
+ IGeckoCustom_p.c \
+ IGeckoCustom_i.c \
+ IGeckoCustom.tlb \
+ $(NULL)
+
+$(MIDL_GENERATED_FILES): done_gen
+
+done_gen: IGeckoCustom.idl
+ $(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/IGeckoCustom.idl
+ touch $@
+
+export:: done_gen
+
+midl_exports := \
+ IGeckoCustom.h \
+ IGeckoCustom_i.c \
+ $(NULL)
+
+INSTALL_TARGETS += midl_exports
+midl_exports_FILES := $(midl_exports)
+midl_exports_DEST = $(DIST)/include
+midl_exports_TARGET := midl
+
+export:: midl
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/moz.build
@@ -0,0 +1,29 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+SOURCES += [
+ '!dlldata.c',
+ '!IGeckoCustom_i.c',
+ '!IGeckoCustom_p.c',
+]
+
+GENERATED_FILES += [
+ 'dlldata.c',
+ 'IGeckoCustom.h',
+ 'IGeckoCustom.tlb',
+ 'IGeckoCustom_i.c',
+ 'IGeckoCustom_p.c',
+]
+
+FINAL_LIBRARY = 'xul'
+
+# The Windows MIDL code generator creates things like:
+#
+# #endif !_MIDL_USE_GUIDDEF_
+#
+# which clang-cl complains about. MSVC doesn't, so turn this warning off.
+if CONFIG['CLANG_CL']:
+ CFLAGS += ['-Wno-extra-tokens']
--- a/accessible/interfaces/ia2/Makefile.in
+++ b/accessible/interfaces/ia2/Makefile.in
@@ -1,16 +1,18 @@
# 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/.
IA2DIR = $(topsrcdir)/other-licenses/ia2
GARBAGE += $(MIDL_GENERATED_FILES) \
$(MIDL_UNUSED_GENERATED_FILES) \
+ midl_done \
+ typelib_done \
$(NULL)
# Please keep this list in sync with the moz.build file until the rest of this
# Makefile is ported over.
MIDL_INTERFACES = \
Accessible2.idl \
Accessible2_2.idl \
Accessible2_3.idl \
@@ -48,20 +50,21 @@ MIDL_LIBRARIES = \
CSRCS = \
dlldata.c \
$(MIDL_INTERFACES:%.idl=%_p.c) \
$(MIDL_INTERFACES:%.idl=%_i.c) \
$(NULL)
MIDL_GENERATED_FILES = \
dlldata.c \
+ $(MIDL_ENUMS:%.idl=%.h) \
$(MIDL_INTERFACES:%.idl=%_p.c) \
$(MIDL_INTERFACES:%.idl=%_i.c) \
$(MIDL_INTERFACES:%.idl=%.h) \
- $(MIDL_ENUMS:%.idl=%.h) \
+ $(MIDL_LIBRARIES:%.idl=%.tlb) \
$(NULL)
# We want to generate a .tlb from MIDL_LIBRARIES, but midl also generates
# a bunch of .h and .c files that we're not interested in.
MIDL_UNUSED_GENERATED_FILES = \
$(MIDL_LIBRARIES:%.idl=%_p.c) \
$(MIDL_LIBRARIES:%.idl=%_i.c) \
$(MIDL_LIBRARIES:%.idl=%.h) \
@@ -75,18 +78,18 @@ midl_FILES := $(filter %.h %_i.c,$(MIDL_
midl_DEST = $(DIST)/include
midl_TARGET := midl
export:: midl
include $(topsrcdir)/config/rules.mk
# generate list of to-be-generated files that are missing
-# but ignore special file dlldata.c
-missing:=$(strip $(foreach onefile,$(strip $(subst dlldata.c,,$(MIDL_GENERATED_FILES))),$(if $(wildcard $(onefile)),,$(onefile))))
+# but ignore special file dlldata.c and .tlb files
+missing:=$(strip $(foreach onefile,$(strip $(patsubst %.tlb,,$(subst dlldata.c,,$(MIDL_GENERATED_FILES)))),$(if $(wildcard $(onefile)),,$(onefile))))
missing_base:=$(sort $(basename $(subst _p.c,,$(subst _i.c,,$(missing)))))
$(MIDL_GENERATED_FILES) : midl_done typelib_done
ifneq ("$(missing)","")
midl_done : FORCE
endif
@@ -94,17 +97,17 @@ endif
midl_done : $(addprefix $(IA2DIR)/,$(MIDL_INTERFACES) $(MIDL_ENUMS))
for idl in $(sort $(subst FORCE,,$?) $(addsuffix .idl,$(addprefix $(IA2DIR)/,$(missing_base)))); do \
$(MIDL) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -Oicf $$idl; \
done
touch $@
# The intent of this rule is to generate the .tlb file that is referenced in the
# .rc file for IA2Marshal.dll
-typelib_done : $(MIDL_LIBRARIES)
+typelib_done : $(addprefix $(srcdir)/,$(MIDL_LIBRARIES))
for idl in $?; do \
- $(MIDL) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -D _MIDL_DECLARE_WIREM_HANDLE -dlldata `basename $$idl .idl`.c -Oicf $$idl; \
+ $(MIDL) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -D _MIDL_DECLARE_WIREM_HANDLE -dlldata `basename $$idl .idl`.c -Oicf $$idl; \
done
touch $@
# This marshall dll is NOT registered in the installer (agreed to by IA2 participants)
register::
regsvr32 -s $(DIST)/bin/$(SHARED_LIBRARY)
--- a/accessible/interfaces/ia2/moz.build
+++ b/accessible/interfaces/ia2/moz.build
@@ -14,16 +14,78 @@ OS_LIBS += [
'uuid',
'kernel32',
'rpcrt4',
'ole32',
'oleaut32',
]
GENERATED_FILES += [
+ 'Accessible2.h',
+ 'Accessible2_2.h',
+ 'Accessible2_2_i.c',
+ 'Accessible2_2_p.c',
+ 'Accessible2_3.h',
+ 'Accessible2_3_i.c',
+ 'Accessible2_3_p.c',
+ 'Accessible2_i.c',
+ 'Accessible2_p.c',
+ 'AccessibleAction.h',
+ 'AccessibleAction_i.c',
+ 'AccessibleAction_p.c',
+ 'AccessibleApplication.h',
+ 'AccessibleApplication_i.c',
+ 'AccessibleApplication_p.c',
+ 'AccessibleComponent.h',
+ 'AccessibleComponent_i.c',
+ 'AccessibleComponent_p.c',
+ 'AccessibleDocument.h',
+ 'AccessibleDocument_i.c',
+ 'AccessibleDocument_p.c',
+ 'AccessibleEditableText.h',
+ 'AccessibleEditableText_i.c',
+ 'AccessibleEditableText_p.c',
+ 'AccessibleEventId.h',
+ 'AccessibleHyperlink.h',
+ 'AccessibleHyperlink_i.c',
+ 'AccessibleHyperlink_p.c',
+ 'AccessibleHypertext.h',
+ 'AccessibleHypertext2.h',
+ 'AccessibleHypertext2_i.c',
+ 'AccessibleHypertext2_p.c',
+ 'AccessibleHypertext_i.c',
+ 'AccessibleHypertext_p.c',
+ 'AccessibleImage.h',
+ 'AccessibleImage_i.c',
+ 'AccessibleImage_p.c',
+ 'AccessibleRelation.h',
+ 'AccessibleRelation_i.c',
+ 'AccessibleRelation_p.c',
+ 'AccessibleRole.h',
+ 'AccessibleStates.h',
+ 'AccessibleTable.h',
+ 'AccessibleTable2.h',
+ 'AccessibleTable2_i.c',
+ 'AccessibleTable2_p.c',
+ 'AccessibleTable_i.c',
+ 'AccessibleTable_p.c',
+ 'AccessibleTableCell.h',
+ 'AccessibleTableCell_i.c',
+ 'AccessibleTableCell_p.c',
+ 'AccessibleText.h',
+ 'AccessibleText2.h',
+ 'AccessibleText2_i.c',
+ 'AccessibleText2_p.c',
+ 'AccessibleText_i.c',
+ 'AccessibleText_p.c',
+ 'AccessibleValue.h',
+ 'AccessibleValue_i.c',
+ 'AccessibleValue_p.c',
+ 'dlldata.c',
+ 'IA2CommonTypes.h',
'IA2Typelib.tlb',
]
RCINCLUDE = 'IA2Marshal.rc'
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
--- a/accessible/interfaces/moz.build
+++ b/accessible/interfaces/moz.build
@@ -1,16 +1,16 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows' and CONFIG['COMPILE_ENVIRONMENT']:
- DIRS += ['msaa', 'ia2']
+ DIRS += ['gecko', 'msaa', 'ia2']
XPIDL_SOURCES += [
'nsIAccessibilityService.idl',
'nsIAccessible.idl',
'nsIAccessibleApplication.idl',
'nsIAccessibleCaretMoveEvent.idl',
'nsIAccessibleDocument.idl',
'nsIAccessibleEditableText.idl',
--- a/accessible/interfaces/msaa/AccessibleMarshal.rc
+++ b/accessible/interfaces/msaa/AccessibleMarshal.rc
@@ -1,5 +1,5 @@
/* 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/. */
-1 typelib ISimpleDOMNode.tlb
+1 typelib ISimpleDOM.tlb
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/msaa/ISimpleDOM.idl
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+// We use #include instead of import here so that MIDL treats these files as
+// part of the current file, thus forcing MIDL to generate proxy info for them.
+#include "ISimpleDOMNode.idl"
+#include "ISimpleDOMDocument.idl"
+#include "ISimpleDOMText.idl"
+
+[
+ uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
+ helpstring("ISimpleDOM Type Library")
+]
+library ISimpleDOM
+{
+ interface ISimpleDOMNode;
+ interface ISimpleDOMText;
+ interface ISimpleDOMDocument;
+};
+
--- a/accessible/interfaces/msaa/ISimpleDOMNode.idl
+++ b/accessible/interfaces/msaa/ISimpleDOMNode.idl
@@ -94,19 +94,16 @@ cpp_quote("//")
cpp_quote("//")
cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
cpp_quote("")
cpp_quote("")
import "objidl.idl";
import "oaidl.idl";
-import "ISimpleDOMText.idl";
-import "ISimpleDOMDocument.idl";
-
[object, uuid(1814ceeb-49e2-407f-af99-fa755a7d2607)]
interface ISimpleDOMNode : IUnknown
{
const unsigned short NODETYPE_ELEMENT = 1;
const unsigned short NODETYPE_ATTRIBUTE = 2;
const unsigned short NODETYPE_TEXT = 3;
const unsigned short NODETYPE_CDATA_SECTION = 4;
const unsigned short NODETYPE_ENTITY_REFERENCE = 5;
@@ -169,20 +166,8 @@ interface ISimpleDOMNode : IUnknown
[propget] HRESULT innerHTML([out, retval] BSTR *innerHTML);
[propget, local] HRESULT localInterface([out][retval] void **localInterface);
[propget] HRESULT language([out, retval] BSTR *language);
}
-
-[
- uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
- helpstring("ISimpleDOM Type Library")
-]
-library ISimpleDOM
-{
- interface ISimpleDOMNode;
- interface ISimpleDOMText;
- interface ISimpleDOMDocument;
-};
-
--- a/accessible/interfaces/msaa/Makefile.in
+++ b/accessible/interfaces/msaa/Makefile.in
@@ -1,52 +1,43 @@
# 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/.
-GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c
+GARBAGE += $(MIDL_GENERATED_FILES) done_gen
MIDL_GENERATED_FILES = \
- ISimpleDOMNode.h \
- ISimpleDOMNode_p.c \
- ISimpleDOMNode_i.c \
- ISimpleDOMDocument.h \
- ISimpleDOMDocument_p.c \
- ISimpleDOMDocument_i.c \
- ISimpleDOMText.h \
- ISimpleDOMText_p.c \
- ISimpleDOMText_i.c \
- $(NULL)
+ dlldata.c \
+ ISimpleDOM.h \
+ ISimpleDOM_i.c \
+ ISimpleDOM_p.c \
+ ISimpleDOM.tlb \
+ $(NULL)
$(MIDL_GENERATED_FILES): done_gen
-done_gen: ISimpleDOMNode.idl \
+done_gen: ISimpleDOM.idl \
+ ISimpleDOMNode.idl \
ISimpleDOMDocument.idl \
ISimpleDOMText.idl
- $(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/ISimpleDOMNode.idl
- $(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMDocument.idl
- $(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMText.idl
+ $(MIDL) $(MIDL_FLAGS) -I $(srcdir) -robust -Oicf $(srcdir)/ISimpleDOM.idl
touch $@
export:: done_gen
# This marshall dll is also registered in the installer
register::
regsvr32 -s $(DIST)/bin/$(SHARED_LIBRARY)
EMBED_MANIFEST_AT = 2
midl_exports := \
- ISimpleDOMDocument.h \
- ISimpleDOMDocument_i.c \
- ISimpleDOMNode.h \
- ISimpleDOMNode_i.c \
- ISimpleDOMText.h \
- ISimpleDOMText_i.c \
+ ISimpleDOM.h \
+ ISimpleDOM_i.c \
$(NULL)
INSTALL_TARGETS += midl_exports
midl_exports_FILES := $(midl_exports)
midl_exports_DEST = $(DIST)/include
midl_exports_TARGET := midl
export:: midl
--- a/accessible/interfaces/msaa/moz.build
+++ b/accessible/interfaces/msaa/moz.build
@@ -3,36 +3,39 @@
# 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/.
GeckoSharedLibrary('AccessibleMarshal', linkage=None)
SOURCES += [
'!dlldata.c',
- '!ISimpleDOMDocument_i.c',
- '!ISimpleDOMDocument_p.c',
- '!ISimpleDOMNode_i.c',
- '!ISimpleDOMNode_p.c',
- '!ISimpleDOMText_i.c',
- '!ISimpleDOMText_p.c',
+ '!ISimpleDOM_i.c',
+ '!ISimpleDOM_p.c',
]
DEFINES['REGISTER_PROXY_DLL'] = True
+# The following line is required to preserve compatibility with older versions
+# of AccessibleMarshal.dll.
+DEFINES['PROXY_CLSID'] = 'IID_ISimpleDOMNode'
DEFFILE = SRCDIR + '/AccessibleMarshal.def'
OS_LIBS += [
'kernel32',
'rpcrt4',
'oleaut32',
]
GENERATED_FILES += [
- 'ISimpleDOMNode.tlb',
+ 'dlldata.c',
+ 'ISimpleDOM.h',
+ 'ISimpleDOM.tlb',
+ 'ISimpleDOM_i.c',
+ 'ISimpleDOM_p.c',
]
RCINCLUDE = 'AccessibleMarshal.rc'
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
#
--- a/accessible/ipc/DocAccessibleChildBase.cpp
+++ b/accessible/ipc/DocAccessibleChildBase.cpp
@@ -84,14 +84,14 @@ void
DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
{
Accessible* parent = aShowEvent->Parent();
uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID());
uint32_t idxInParent = aShowEvent->GetAccessible()->IndexInParent();
nsTArray<AccessibleData> shownTree;
ShowEventData data(parentID, idxInParent, shownTree);
SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
- SendShowEvent(data, aShowEvent->IsFromUserInput());
+ MaybeSendShowEvent(data, aShowEvent->IsFromUserInput());
}
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/DocAccessibleChildBase.h
+++ b/accessible/ipc/DocAccessibleChildBase.h
@@ -4,16 +4,17 @@
* 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/. */
#ifndef mozilla_a11y_DocAccessibleChildBase_h
#define mozilla_a11y_DocAccessibleChildBase_h
#include "mozilla/a11y/DocAccessible.h"
#include "mozilla/a11y/PDocAccessibleChild.h"
+#include "mozilla/Unused.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace a11y {
class Accessible;
class AccShowEvent;
@@ -33,20 +34,19 @@ public:
MOZ_ASSERT(!mDoc);
if (mDoc) {
mDoc->SetIPCDoc(nullptr);
}
MOZ_COUNT_DTOR(DocAccessibleChildBase);
}
- void Shutdown()
+ virtual void Shutdown()
{
- mDoc->SetIPCDoc(nullptr);
- mDoc = nullptr;
+ DetachDocument();
SendShutdown();
}
void ShowEvent(AccShowEvent* aShowEvent);
virtual void ActorDestroy(ActorDestroyReason) override
{
if (!mDoc) {
@@ -56,15 +56,26 @@ public:
mDoc->SetIPCDoc(nullptr);
mDoc = nullptr;
}
protected:
static uint32_t InterfacesFor(Accessible* aAcc);
static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree);
+ virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser)
+ { Unused << SendShowEvent(aData, aFromUser); }
+
+ void DetachDocument()
+ {
+ if (mDoc) {
+ mDoc->SetIPCDoc(nullptr);
+ mDoc = nullptr;
+ }
+ }
+
DocAccessible* mDoc;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_DocAccessibleChildBase_h
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -7,65 +7,81 @@
#include "DocAccessibleParent.h"
#include "mozilla/a11y/Platform.h"
#include "mozilla/dom/TabParent.h"
#include "xpcAccessibleDocument.h"
#include "xpcAccEvents.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
+#if defined(XP_WIN)
+#include "AccessibleWrap.h"
+#include "Compatibility.h"
+#include "nsWinUtils.h"
+#include "RootAccessible.h"
+#endif
+
namespace mozilla {
namespace a11y {
+uint64_t DocAccessibleParent::sMaxDocID = 0;
mozilla::ipc::IPCResult
DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
const bool& aFromUser)
{
if (mShutdown)
return IPC_OK();
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
if (aData.NewTree().IsEmpty()) {
NS_ERROR("no children being added");
return IPC_FAIL_NO_REASON(this);
}
ProxyAccessible* parent = GetAccessible(aData.ID());
// XXX This should really never happen, but sometimes we fail to fire the
// required show events.
if (!parent) {
NS_ERROR("adding child to unknown accessible");
+#ifdef DEBUG
+ return IPC_FAIL(this, "unknown parent accessible");
+#else
return IPC_OK();
+#endif
}
uint32_t newChildIdx = aData.Idx();
if (newChildIdx > parent->ChildrenCount()) {
NS_ERROR("invalid index to add child at");
+#ifdef DEBUG
+ return IPC_FAIL(this, "invalid index");
+#else
return IPC_OK();
+#endif
}
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
MOZ_ASSERT(consumed == aData.NewTree().Length());
// XXX This shouldn't happen, but if we failed to add children then the below
// is pointless and can crash.
if (!consumed) {
- return IPC_OK();
+ return IPC_FAIL(this, "failed to add children");
}
#ifdef DEBUG
for (uint32_t i = 0; i < consumed; i++) {
uint64_t id = aData.NewTree()[i].ID();
MOZ_ASSERT(mAccessibles.GetEntry(id));
}
#endif
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
ProxyAccessible* target = parent->ChildAt(newChildIdx);
ProxyShowHideEvent(target, parent, true, aFromUser);
if (!nsCoreUtils::AccEventObserversExist()) {
return IPC_OK();
}
@@ -132,17 +148,17 @@ DocAccessibleParent::AddSubtree(ProxyAcc
mozilla::ipc::IPCResult
DocAccessibleParent::RecvHideEvent(const uint64_t& aRootID,
const bool& aFromUser)
{
if (mShutdown)
return IPC_OK();
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
// We shouldn't actually need this because mAccessibles shouldn't have an
// entry for the document itself, but it doesn't hurt to be explicit.
if (!aRootID) {
NS_ERROR("trying to hide entire document?");
return IPC_FAIL_NO_REASON(this);
}
@@ -174,28 +190,32 @@ DocAccessibleParent::RecvHideEvent(const
nsIDOMNode* node = nullptr;
event = new xpcAccHideEvent(type, xpcAcc, doc, node, aFromUser, xpcParent,
xpcNext, xpcPrev);
}
parent->RemoveChild(root);
root->Shutdown();
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
if (event) {
nsCoreUtils::DispatchAccEvent(Move(event));
}
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvEvent(const uint64_t& aID, const uint32_t& aEventType)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
ProxyAccessible* proxy = GetAccessible(aID);
if (!proxy) {
NS_ERROR("no proxy for event!");
return IPC_OK();
}
ProxyEvent(proxy, aEventType);
@@ -214,16 +234,20 @@ DocAccessibleParent::RecvEvent(const uin
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvStateChangeEvent(const uint64_t& aID,
const uint64_t& aState,
const bool& aEnabled)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
ProxyAccessible* target = GetAccessible(aID);
if (!target) {
NS_ERROR("we don't know about the target of a state change event!");
return IPC_OK();
}
ProxyStateChangeEvent(target, aState, aEnabled);
@@ -244,16 +268,20 @@ DocAccessibleParent::RecvStateChangeEven
nsCoreUtils::DispatchAccEvent(Move(event));
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
ProxyAccessible* proxy = GetAccessible(aID);
if (!proxy) {
NS_ERROR("unknown caret move event target!");
return IPC_OK();
}
ProxyCaretMoveEvent(proxy, aOffset);
@@ -276,16 +304,20 @@ DocAccessibleParent::RecvCaretMoveEvent(
mozilla::ipc::IPCResult
DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
const nsString& aStr,
const int32_t& aStart,
const uint32_t& aLen,
const bool& aIsInsert,
const bool& aFromUser)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
ProxyAccessible* target = GetAccessible(aID);
if (!target) {
NS_ERROR("text change event target is unknown!");
return IPC_OK();
}
ProxyTextChangeEvent(target, aStr, aStart, aLen, aIsInsert, aFromUser);
@@ -306,16 +338,20 @@ DocAccessibleParent::RecvTextChangeEvent
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID,
const uint32_t& aType)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
ProxyAccessible* target = GetAccessible(aID);
ProxyAccessible* widget = GetAccessible(aWidgetID);
if (!target || !widget) {
NS_ERROR("invalid id in selection event");
return IPC_OK();
}
ProxySelectionEvent(target, widget, aType);
@@ -329,129 +365,198 @@ DocAccessibleParent::RecvSelectionEvent(
nsCoreUtils::DispatchAccEvent(Move(event));
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvRoleChangedEvent(const uint32_t& aRole)
{
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
if (aRole >= roles::LAST_ROLE) {
NS_ERROR("child sent bad role in RoleChangedEvent");
return IPC_FAIL_NO_REASON(this);
}
mRole = static_cast<a11y::role>(aRole);
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID)
{
// One document should never directly be the child of another.
// We should always have at least an outer doc accessible in between.
MOZ_ASSERT(aID);
if (!aID)
- return IPC_FAIL_NO_REASON(this);
+ return IPC_FAIL(this, "ID is 0!");
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ if (mShutdown) {
+ return IPC_OK();
+ }
+
+ MOZ_ASSERT(CheckDocTree());
auto childDoc = static_cast<DocAccessibleParent*>(aChildDoc);
childDoc->Unbind();
- bool result = AddChildDoc(childDoc, aID, false);
+ ipc::IPCResult result = AddChildDoc(childDoc, aID, false);
MOZ_ASSERT(result);
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
+#ifdef DEBUG
if (!result) {
- return IPC_FAIL_NO_REASON(this);
+ return result;
}
- return IPC_OK();
+#else
+ result = IPC_OK();
+#endif
+
+ return result;
}
-bool
+ipc::IPCResult
DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
uint64_t aParentID, bool aCreating)
{
// We do not use GetAccessible here because we want to be sure to not get the
// document it self.
ProxyEntry* e = mAccessibles.GetEntry(aParentID);
- if (!e)
- return false;
+ if (!e) {
+ return IPC_FAIL(this, "binding to nonexistant proxy!");
+ }
ProxyAccessible* outerDoc = e->mProxy;
MOZ_ASSERT(outerDoc);
// OuterDocAccessibles are expected to only have a document as a child.
// However for compatibility we tolerate replacing one document with another
// here.
if (outerDoc->ChildrenCount() > 1 ||
(outerDoc->ChildrenCount() == 1 && !outerDoc->ChildAt(0)->IsDoc())) {
- return false;
+ return IPC_FAIL(this, "binding to proxy that can't be a outerDoc!");
}
- aChildDoc->mParent = outerDoc;
+ aChildDoc->SetParent(outerDoc);
outerDoc->SetChildDoc(aChildDoc);
- mChildDocs.AppendElement(aChildDoc);
- aChildDoc->mParentDoc = this;
+ mChildDocs.AppendElement(aChildDoc->mActorID);
+ aChildDoc->mParentDoc = mActorID;
if (aCreating) {
ProxyCreated(aChildDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
}
- return true;
+ return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvShutdown()
{
Destroy();
- if (!static_cast<dom::TabParent*>(Manager())->IsDestroyed()) {
+ auto mgr = static_cast<dom::TabParent*>(Manager());
+ if (!mgr->IsDestroyed()) {
if (!PDocAccessibleParent::Send__delete__(this)) {
- return IPC_FAIL_NO_REASON(this);
+ return IPC_FAIL_NO_REASON(mgr);
}
}
return IPC_OK();
}
void
DocAccessibleParent::Destroy()
{
- NS_ASSERTION(mChildDocs.IsEmpty(),
- "why weren't the child docs destroyed already?");
- MOZ_ASSERT(!mShutdown);
+ // If we are already shutdown that is because our containing tab parent is
+ // shutting down in which case we don't need to do anything.
+ if (mShutdown) {
+ return;
+ }
+
mShutdown = true;
+ MOZ_DIAGNOSTIC_ASSERT(LiveDocs().Contains(mActorID));
uint32_t childDocCount = mChildDocs.Length();
- for (uint32_t i = childDocCount - 1; i < childDocCount; i--)
- mChildDocs[i]->Destroy();
+ for (uint32_t i = 0; i < childDocCount; i++) {
+ for (uint32_t j = i + 1; j < childDocCount; j++) {
+ MOZ_DIAGNOSTIC_ASSERT(mChildDocs[i] != mChildDocs[j]);
+ }
+ }
+
+ // XXX This indirection through the hash map of live documents shouldn't be
+ // needed, but be paranoid for now.
+ int32_t actorID = mActorID;
+ for (uint32_t i = childDocCount - 1; i < childDocCount; i--) {
+ DocAccessibleParent* thisDoc = LiveDocs().Get(actorID);
+ MOZ_ASSERT(thisDoc);
+ if (!thisDoc) {
+ return;
+ }
+
+ thisDoc->ChildDocAt(i)->Destroy();
+ }
for (auto iter = mAccessibles.Iter(); !iter.Done(); iter.Next()) {
MOZ_ASSERT(iter.Get()->mProxy != this);
ProxyDestroyed(iter.Get()->mProxy);
iter.Remove();
}
- DocManager::NotifyOfRemoteDocShutdown(this);
- ProxyDestroyed(this);
- if (mParentDoc)
- mParentDoc->RemoveChildDoc(this);
+ DocAccessibleParent* thisDoc = LiveDocs().Get(actorID);
+ MOZ_ASSERT(thisDoc);
+ if (!thisDoc) {
+ return;
+ }
+
+ // The code above should have already completely cleared these, but to be
+ // extra safe make sure they are cleared here.
+ thisDoc->mAccessibles.Clear();
+ thisDoc->mChildDocs.Clear();
+
+ DocManager::NotifyOfRemoteDocShutdown(thisDoc);
+ thisDoc = LiveDocs().Get(actorID);
+ MOZ_ASSERT(thisDoc);
+ if (!thisDoc) {
+ return;
+ }
+
+ ProxyDestroyed(thisDoc);
+ thisDoc = LiveDocs().Get(actorID);
+ MOZ_ASSERT(thisDoc);
+ if (!thisDoc) {
+ return;
+ }
+
+ if (DocAccessibleParent* parentDoc = thisDoc->ParentDoc())
+ parentDoc->RemoveChildDoc(thisDoc);
else if (IsTopLevel())
GetAccService()->RemoteDocShutdown(this);
}
+DocAccessibleParent*
+DocAccessibleParent::ParentDoc() const
+{
+ if (mParentDoc == kNoParentDoc) {
+ return nullptr;
+ }
+
+ return LiveDocs().Get(mParentDoc);
+}
+
bool
DocAccessibleParent::CheckDocTree() const
{
size_t childDocs = mChildDocs.Length();
for (size_t i = 0; i < childDocs; i++) {
- if (!mChildDocs[i] || mChildDocs[i]->mParentDoc != this)
+ const DocAccessibleParent* childDoc = ChildDocAt(i);
+ if (!childDoc || childDoc->ParentDoc() != this)
return false;
- if (!mChildDocs[i]->CheckDocTree()) {
+ if (!childDoc->CheckDocTree()) {
return false;
}
}
return true;
}
xpcAccessibleGeneric*
@@ -459,37 +564,101 @@ DocAccessibleParent::GetXPCAccessible(Pr
{
xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
MOZ_ASSERT(doc);
return doc->GetXPCAccessible(aProxy);
}
#if defined(XP_WIN)
+void
+DocAccessibleParent::MaybeInitWindowEmulation()
+{
+ if (!nsWinUtils::IsWindowEmulationStarted()) {
+ return;
+ }
+
+ // XXX get the bounds from the tabParent instead of poking at accessibles
+ // which might not exist yet.
+ Accessible* outerDoc = OuterDocOfRemoteBrowser();
+ if (!outerDoc) {
+ return;
+ }
+
+ RootAccessible* rootDocument = outerDoc->RootAccessible();
+ MOZ_ASSERT(rootDocument);
+
+ bool isActive = true;
+ nsIntRect rect(CW_USEDEFAULT, CW_USEDEFAULT, 0, 0);
+ if (Compatibility::IsDolphin()) {
+ rect = Bounds();
+ nsIntRect rootRect = rootDocument->Bounds();
+ rect.x = rootRect.x - rect.x;
+ rect.y -= rootRect.y;
+
+ auto tab = static_cast<dom::TabParent*>(Manager());
+ tab->GetDocShellIsActive(&isActive);
+ }
+
+ IAccessibleHolder hWndAccHolder;
+ HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
+ HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
+ parentWnd, rect.x, rect.y,
+ rect.width, rect.height,
+ isActive);
+ if (hWnd) {
+ // Attach accessible document to the emulated native window
+ ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this);
+ SetEmulatedWindowHandle(hWnd);
+ IAccessible* rawHWNDAcc = nullptr;
+ if (SUCCEEDED(::AccessibleObjectFromWindow(hWnd, OBJID_WINDOW,
+ IID_IAccessible,
+ (void**)&rawHWNDAcc))) {
+ hWndAccHolder.Set(IAccessibleHolder::COMPtrType(rawHWNDAcc));
+ }
+ }
+
+ Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
+ hWndAccHolder);
+}
+
/**
* @param aCOMProxy COM Proxy to the document in the content process.
- * @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
- * the parent of the document. The content process will use this
- * proxy when traversing up across the content/chrome boundary.
*/
-mozilla::ipc::IPCResult
-DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
- IAccessibleHolder* aParentCOMProxy)
+void
+DocAccessibleParent::SendParentCOMProxy()
{
- RefPtr<IAccessible> ptr(aCOMProxy.Get());
- SetCOMInterface(ptr);
+ // Make sure that we're not racing with a tab shutdown
+ auto tab = static_cast<dom::TabParent*>(Manager());
+ MOZ_ASSERT(tab);
+ if (tab->IsDestroyed()) {
+ return;
+ }
Accessible* outerDoc = OuterDocOfRemoteBrowser();
- IAccessible* rawNative = nullptr;
- if (outerDoc) {
- outerDoc->GetNativeInterface((void**) &rawNative);
+ if (!outerDoc) {
+ return;
}
- aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
- return IPC_OK();
+ IAccessible* rawNative = nullptr;
+ outerDoc->GetNativeInterface((void**) &rawNative);
+ MOZ_ASSERT(rawNative);
+
+ IAccessibleHolder::COMPtrType ptr(rawNative);
+ IAccessibleHolder holder(Move(ptr));
+ Unused << PDocAccessibleParent::SendParentCOMProxy(holder);
+}
+
+void
+DocAccessibleParent::SetEmulatedWindowHandle(HWND aWindowHandle)
+{
+ if (!aWindowHandle && mEmulatedWindowHandle && IsTopLevel()) {
+ ::DestroyWindow(mEmulatedWindowHandle);
+ }
+ mEmulatedWindowHandle = aWindowHandle;
}
mozilla::ipc::IPCResult
DocAccessibleParent::RecvGetWindowedPluginIAccessible(
const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy)
{
#if defined(MOZ_CONTENT_SANDBOX)
// We don't actually want the accessible object for aHwnd, but rather the
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -23,31 +23,53 @@ class xpcAccessibleGeneric;
* These objects live in the main process and comunicate with and represent
* an accessible document in a content process.
*/
class DocAccessibleParent : public ProxyAccessible,
public PDocAccessibleParent
{
public:
DocAccessibleParent() :
- ProxyAccessible(this), mParentDoc(nullptr),
+ ProxyAccessible(this), mParentDoc(kNoParentDoc),
mTopLevel(false), mShutdown(false)
- { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); }
+#if defined(XP_WIN)
+ , mEmulatedWindowHandle(nullptr)
+#endif // defined(XP_WIN)
+ {
+ MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
+ sMaxDocID++;
+ mActorID = sMaxDocID;
+ MOZ_ASSERT(!LiveDocs().Get(mActorID));
+ LiveDocs().Put(mActorID, this);
+ }
~DocAccessibleParent()
{
+ LiveDocs().Remove(mActorID);
MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
MOZ_ASSERT(mChildDocs.Length() == 0);
MOZ_ASSERT(!ParentDoc());
}
void SetTopLevel() { mTopLevel = true; }
bool IsTopLevel() const { return mTopLevel; }
bool IsShutdown() const { return mShutdown; }
+ /**
+ * Mark this actor as shutdown without doing any cleanup. This should only
+ * be called on actors that have just been initialized, so probably only from
+ * RecvPDocAccessibleConstructor.
+ */
+ void MarkAsShutdown()
+ {
+ MOZ_ASSERT(mChildDocs.IsEmpty());
+ MOZ_ASSERT(mAccessibles.Count() == 0);
+ mShutdown = true;
+ }
+
/*
* Called when a message from a document in a child process notifies the main
* process it is firing an event.
*/
virtual mozilla::ipc::IPCResult RecvEvent(const uint64_t& aID, const uint32_t& aType)
override;
virtual mozilla::ipc::IPCResult RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
@@ -75,50 +97,56 @@ public:
virtual mozilla::ipc::IPCResult RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
void Unbind()
{
if (DocAccessibleParent* parent = ParentDoc()) {
parent->RemoveChildDoc(this);
}
- mParent = nullptr;
+ SetParent(nullptr);
}
virtual mozilla::ipc::IPCResult RecvShutdown() override;
void Destroy();
virtual void ActorDestroy(ActorDestroyReason aWhy) override
{
- MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
+ MOZ_ASSERT(CheckDocTree());
if (!mShutdown)
Destroy();
}
/*
* Return the main processes representation of the parent document (if any)
* of the document this object represents.
*/
- DocAccessibleParent* ParentDoc() const { return mParentDoc; }
+ DocAccessibleParent* ParentDoc() const;
+ static const uint64_t kNoParentDoc = UINT64_MAX;
/*
* Called when a document in a content process notifies the main process of a
* new child document.
*/
- bool AddChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID,
- bool aCreating = true);
+ ipc::IPCResult AddChildDoc(DocAccessibleParent* aChildDoc,
+ uint64_t aParentID, bool aCreating = true);
/*
* Called when the document in the content process this object represents
* notifies the main process a child document has been removed.
*/
void RemoveChildDoc(DocAccessibleParent* aChildDoc)
{
- aChildDoc->Parent()->SetChildDoc(nullptr);
- mChildDocs.RemoveElement(aChildDoc);
- aChildDoc->mParentDoc = nullptr;
+ ProxyAccessible* parent = aChildDoc->Parent();
+ MOZ_ASSERT(parent);
+ if (parent) {
+ aChildDoc->Parent()->ClearChildDoc(aChildDoc);
+ }
+ DebugOnly<bool> result = mChildDocs.RemoveElement(aChildDoc->mActorID);
+ aChildDoc->mParentDoc = kNoParentDoc;
+ MOZ_ASSERT(result);
MOZ_ASSERT(aChildDoc->mChildDocs.Length() == 0);
}
void RemoveAccessible(ProxyAccessible* aAccessible)
{
MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID()));
mAccessibles.RemoveEntry(aAccessible->ID());
}
@@ -135,24 +163,33 @@ public:
return e ? e->mProxy : nullptr;
}
const ProxyAccessible* GetAccessible(uintptr_t aID) const
{ return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); }
size_t ChildDocCount() const { return mChildDocs.Length(); }
const DocAccessibleParent* ChildDocAt(size_t aIdx) const
- { return mChildDocs[aIdx]; }
+ { return const_cast<DocAccessibleParent*>(this)->ChildDocAt(aIdx); }
+ DocAccessibleParent* ChildDocAt(size_t aIdx)
+ { return LiveDocs().Get(mChildDocs[aIdx]); }
#if defined(XP_WIN)
- virtual mozilla::ipc::IPCResult RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
- IAccessibleHolder* aParentCOMProxy) override;
+ void MaybeInitWindowEmulation();
+ void SendParentCOMProxy();
virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible(
const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override;
+
+ /**
+ * Set emulated native window handle for a document.
+ * @param aWindowHandle emulated native window handle
+ */
+ void SetEmulatedWindowHandle(HWND aWindowHandle);
+ HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
#endif
private:
class ProxyEntry : public PLDHashEntryHdr
{
public:
explicit ProxyEntry(const void*) : mProxy(nullptr) {}
@@ -176,24 +213,38 @@ private:
};
uint32_t AddSubtree(ProxyAccessible* aParent,
const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
uint32_t aIdxInParent);
MOZ_MUST_USE bool CheckDocTree() const;
xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
- nsTArray<DocAccessibleParent*> mChildDocs;
- DocAccessibleParent* mParentDoc;
+ nsTArray<uint64_t> mChildDocs;
+ uint64_t mParentDoc;
+
+#if defined(XP_WIN)
+ // The handle associated with the emulated window that contains this document
+ HWND mEmulatedWindowHandle;
+#endif
/*
* Conceptually this is a map from IDs to proxies, but we store the ID in the
* proxy object so we can't use a real map.
*/
nsTHashtable<ProxyEntry> mAccessibles;
+ uint64_t mActorID;
bool mTopLevel;
bool mShutdown;
+
+ static uint64_t sMaxDocID;
+ static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*>&
+ LiveDocs()
+ {
+ static nsDataHashtable<nsUint64HashKey, DocAccessibleParent*> sLiveDocs;
+ return sLiveDocs;
+ }
};
}
}
#endif
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/IPCTypes.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_a11y_IPCTypes_h
+#define mozilla_a11y_IPCTypes_h
+
+/**
+ * Since IPDL does not support preprocessing, this header file allows us to
+ * define types used by PDocAccessible differently depending on platform.
+ */
+
+#if defined(XP_WIN) && defined(ACCESSIBILITY)
+
+// So that we don't include a bunch of other Windows junk.
+#if !defined(COM_NO_WINDOWS_H)
+#define COM_NO_WINDOWS_H
+#endif // !defined(COM_NO_WINDOWS_H)
+
+// COM headers pull in MSXML which conflicts with our own XMLDocument class.
+// This define excludes those conflicting definitions.
+#if !defined(__XMLDocument_FWD_DEFINED__)
+#define __XMLDocument_FWD_DEFINED__
+#endif // !defined(__XMLDocument_FWD_DEFINED__)
+
+#include "mozilla/a11y/COMPtrTypes.h"
+
+// This define in rpcndr.h messes up our code, so we must undefine it after
+// COMPtrTypes.h has been included.
+#if defined(small)
+#undef small
+#endif // defined(small)
+
+#else
+
+namespace mozilla {
+namespace a11y {
+
+typedef uint32_t IAccessibleHolder;
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // defined(XP_WIN) && defined(ACCESSIBILITY)
+
+#endif // mozilla_a11y_IPCTypes_h
+
--- a/accessible/ipc/ProxyAccessibleBase.cpp
+++ b/accessible/ipc/ProxyAccessibleBase.cpp
@@ -20,54 +20,68 @@
namespace mozilla {
namespace a11y {
template <class Derived>
void
ProxyAccessibleBase<Derived>::Shutdown()
{
MOZ_DIAGNOSTIC_ASSERT(!IsDoc());
- NS_ASSERTION(!mOuterDoc, "Why do we still have a child doc?");
xpcAccessibleDocument* xpcDoc =
GetAccService()->GetCachedXPCDocument(Document());
if (xpcDoc) {
xpcDoc->NotifyOfShutdown(static_cast<Derived*>(this));
}
// XXX Ideally this wouldn't be necessary, but it seems OuterDoc accessibles
// can be destroyed before the doc they own.
+ uint32_t childCount = mChildren.Length();
if (!mOuterDoc) {
- uint32_t childCount = mChildren.Length();
for (uint32_t idx = 0; idx < childCount; idx++)
mChildren[idx]->Shutdown();
} else {
- if (mChildren.Length() != 1)
- MOZ_CRASH("outer doc doesn't own adoc!");
-
- mChildren[0]->AsDoc()->Unbind();
+ if (childCount > 1) {
+ MOZ_CRASH("outer doc has too many documents!");
+ } else if (childCount == 1) {
+ mChildren[0]->AsDoc()->Unbind();
+ }
}
mChildren.Clear();
ProxyDestroyed(static_cast<Derived*>(this));
mDoc->RemoveAccessible(static_cast<Derived*>(this));
}
template <class Derived>
void
-ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aParent)
+ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc)
{
- if (aParent) {
- MOZ_ASSERT(mChildren.IsEmpty());
- mChildren.AppendElement(aParent);
- mOuterDoc = true;
+ // DocAccessibleParent::AddChildDoc tolerates replacing one document with
+ // another. We must reflect that here.
+ MOZ_ASSERT(aChildDoc);
+ MOZ_ASSERT(mChildren.Length() <= 1);
+ if (mChildren.IsEmpty()) {
+ mChildren.AppendElement(aChildDoc);
} else {
- MOZ_ASSERT(mChildren.Length() == 1);
- mChildren.Clear();
- mOuterDoc = false;
+ mChildren.ReplaceElementAt(0, aChildDoc);
}
+ mOuterDoc = true;
+}
+
+template <class Derived>
+void
+ProxyAccessibleBase<Derived>::ClearChildDoc(DocAccessibleParent* aChildDoc)
+{
+ MOZ_ASSERT(aChildDoc);
+ // This is possible if we're replacing one document with another: Doc 1
+ // has not had a chance to remove itself, but was already replaced by Doc 2
+ // in SetChildDoc(). This could result in two subsequent calls to
+ // ClearChildDoc() even though mChildren.Length() == 1.
+ MOZ_ASSERT(mChildren.Length() <= 1);
+ mChildren.RemoveElement(aChildDoc);
}
template <class Derived>
bool
ProxyAccessibleBase<Derived>::MustPruneChildren() const
{
// this is the equivalent to nsAccUtils::MustPrune for proxies and should be
// kept in sync with that.
@@ -148,12 +162,53 @@ ProxyAccessibleBase<Derived>::OuterDocOf
if (!frame)
return nullptr;
DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
}
+template<class Derived>
+void
+ProxyAccessibleBase<Derived>::SetParent(Derived* aParent)
+{
+ MOZ_ASSERT(IsDoc(), "we should only reparent documents");
+ if (!aParent) {
+ mParent = kNoParent;
+ } else {
+ MOZ_ASSERT(!aParent->IsDoc());
+ mParent = aParent->ID();
+ }
+}
+
+template<class Derived>
+Derived*
+ProxyAccessibleBase<Derived>::Parent() const
+{
+ if (mParent == kNoParent) {
+ return nullptr;
+ }
+
+ // if we are not a document then are parent is another proxy in the same
+ // document. That means we can just ask our document for the proxy with our
+ // parent id.
+ if (!IsDoc()) {
+ return Document()->GetAccessible(mParent);
+ }
+
+ // If we are a top level document then our parent is not a proxy.
+ if (AsDoc()->IsTopLevel()) {
+ return nullptr;
+ }
+
+ // Finally if we are a non top level document then our parent id is for a
+ // proxy in our parent document so get the proxy from there.
+ DocAccessibleParent* parentDoc = AsDoc()->ParentDoc();
+ MOZ_ASSERT(parentDoc);
+ MOZ_ASSERT(mParent);
+ return parentDoc->GetAccessible(mParent);
+}
+
template class ProxyAccessibleBase<ProxyAccessible>;
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/ProxyAccessibleBase.h
+++ b/accessible/ipc/ProxyAccessibleBase.h
@@ -73,28 +73,29 @@ public:
Parent()->mChildren.IndexOf(static_cast<const Derived*>(this)); }
uint32_t EmbeddedChildCount() const;
int32_t IndexOfEmbeddedChild(const Derived* aChild);
Derived* EmbeddedChildAt(size_t aChildIdx);
bool MustPruneChildren() const;
void Shutdown();
- void SetChildDoc(DocAccessibleParent*);
+ void SetChildDoc(DocAccessibleParent* aChildDoc);
+ void ClearChildDoc(DocAccessibleParent* aChildDoc);
/**
* Remove The given child.
*/
void RemoveChild(Derived* aChild)
{ mChildren.RemoveElement(aChild); }
/**
* Return the proxy for the parent of the wrapped accessible.
*/
- Derived* Parent() const { return mParent; }
+ Derived* Parent() const;
Accessible* OuterDocOfRemoteBrowser() const;
/**
* Get the role of the accessible we're proxying.
*/
role Role() const { return mRole; }
@@ -152,39 +153,42 @@ public:
mRole == roles::GRID_CELL ||
mRole == roles::MATHML_CELL);
}
protected:
ProxyAccessibleBase(uint64_t aID, Derived* aParent,
DocAccessibleParent* aDoc, role aRole,
uint32_t aInterfaces)
- : mParent(aParent)
+ : mParent(aParent->ID())
, mDoc(aDoc)
, mWrapper(0)
, mID(aID)
, mRole(aRole)
, mOuterDoc(false)
, mIsDoc(false)
, mHasValue(aInterfaces & Interfaces::VALUE)
, mIsHyperLink(aInterfaces & Interfaces::HYPERLINK)
, mIsHyperText(aInterfaces & Interfaces::HYPERTEXT)
{
}
explicit ProxyAccessibleBase(DocAccessibleParent* aThisAsDoc) :
- mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0),
+ mParent(kNoParent), mDoc(aThisAsDoc), mWrapper(0), mID(0),
mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
mIsHyperLink(false), mIsHyperText(false)
{}
protected:
- Derived* mParent;
+ void SetParent(Derived* aParent);
private:
+ uintptr_t mParent;
+ static const uintptr_t kNoParent = UINTPTR_MAX;
+
friend Derived;
nsTArray<Derived*> mChildren;
DocAccessibleParent* mDoc;
uintptr_t mWrapper;
uint64_t mID;
protected:
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -24,16 +24,20 @@ else:
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',
]
+EXPORTS.mozilla.a11y += [
+ 'IPCTypes.h',
+]
+
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG['ACCESSIBILITY']:
EXPORTS.mozilla.a11y += [
'DocAccessibleChildBase.h',
'DocAccessibleParent.h',
'ProxyAccessibleBase.h',
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -4,40 +4,249 @@
* 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/. */
#include "DocAccessibleChild.h"
#include "Accessible-inl.h"
#include "mozilla/a11y/PlatformChild.h"
#include "mozilla/ClearOnShutdown.h"
+#include "RootAccessible.h"
namespace mozilla {
namespace a11y {
static StaticAutoPtr<PlatformChild> sPlatformChild;
DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
: DocAccessibleChildBase(aDoc)
+ , mEmulatedWindowHandle(nullptr)
+ , mIsRemoteConstructed(false)
{
MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
if (!sPlatformChild) {
sPlatformChild = new PlatformChild();
ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown);
}
}
DocAccessibleChild::~DocAccessibleChild()
{
MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
}
void
-DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
+DocAccessibleChild::Shutdown()
+{
+ if (IsConstructedInParentProcess()) {
+ DocAccessibleChildBase::Shutdown();
+ return;
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedShutdown>(this));
+ DetachDocument();
+}
+
+ipc::IPCResult
+DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy)
+{
+ MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull());
+ mParentProxy.reset(const_cast<IAccessibleHolder&>(aParentCOMProxy).Release());
+ SetConstructedInParentProcess();
+
+ for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) {
+ mDeferredEvents[i]->Dispatch();
+ }
+
+ mDeferredEvents.Clear();
+
+ return IPC_OK();
+}
+
+ipc::IPCResult
+DocAccessibleChild::RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
+ const IAccessibleHolder& aEmulatedWindowCOMProxy)
+{
+ mEmulatedWindowHandle = reinterpret_cast<HWND>(aEmulatedWindowHandle);
+ if (!aEmulatedWindowCOMProxy.IsNull()) {
+ MOZ_ASSERT(!mEmulatedWindowProxy);
+ mEmulatedWindowProxy.reset(
+ const_cast<IAccessibleHolder&>(aEmulatedWindowCOMProxy).Release());
+ }
+
+ return IPC_OK();
+}
+
+void
+DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent)
+{
+ DocAccessibleChild* topLevelIPCDoc = nullptr;
+
+ if (mDoc && mDoc->IsRoot()) {
+ topLevelIPCDoc = this;
+ } else {
+ auto tabChild = static_cast<dom::TabChild*>(Manager());
+ if (!tabChild) {
+ return;
+ }
+
+ nsTArray<PDocAccessibleChild*> ipcDocAccs;
+ tabChild->ManagedPDocAccessibleChild(ipcDocAccs);
+
+ // Look for the top-level DocAccessibleChild - there will only be one
+ // per TabChild.
+ for (uint32_t i = 0, l = ipcDocAccs.Length(); i < l; ++i) {
+ auto ipcDocAcc = static_cast<DocAccessibleChild*>(ipcDocAccs[i]);
+ if (ipcDocAcc->mDoc && ipcDocAcc->mDoc->IsRoot()) {
+ topLevelIPCDoc = ipcDocAcc;
+ break;
+ }
+ }
+ }
+
+ if (topLevelIPCDoc) {
+ topLevelIPCDoc->mDeferredEvents.AppendElement(Move(aEvent));
+ }
+}
+
+bool
+DocAccessibleChild::SendEvent(const uint64_t& aID, const uint32_t& aType)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendEvent(aID, aType);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedEvent>(this, aID, aType));
+ return false;
+}
+
+void
+DocAccessibleChild::MaybeSendShowEvent(ShowEventData& aData, bool aFromUser)
+{
+ if (IsConstructedInParentProcess()) {
+ Unused << SendShowEvent(aData, aFromUser);
+ return;
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedShow>(this, aData, aFromUser));
+}
+
+bool
+DocAccessibleChild::SendHideEvent(const uint64_t& aRootID,
+ const bool& aFromUser)
{
- IAccessibleHolder parentProxy;
- PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy);
- mParentProxy.reset(parentProxy.Release());
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendHideEvent(aRootID, aFromUser);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedHide>(this, aRootID, aFromUser));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendStateChangeEvent(const uint64_t& aID,
+ const uint64_t& aState,
+ const bool& aEnabled)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendStateChangeEvent(aID, aState, aEnabled);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedStateChange>(this, aID, aState,
+ aEnabled));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
+ const int32_t& aOffset)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendCaretMoveEvent(aID, aOffset);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedCaretMove>(this, aID, aOffset));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID,
+ const nsString& aStr,
+ const int32_t& aStart,
+ const uint32_t& aLen,
+ const bool& aIsInsert,
+ const bool& aFromUser)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart,
+ aLen, aIsInsert, aFromUser);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedTextChange>(this, aID, aStr, aStart,
+ aLen, aIsInsert, aFromUser));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendSelectionEvent(const uint64_t& aID,
+ const uint64_t& aWidgetID,
+ const uint32_t& aType)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendSelectionEvent(aID, aWidgetID, aType);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedSelection>(this, aID,
+ aWidgetID,
+ aType));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendRoleChangedEvent(const uint32_t& aRole)
+{
+ if (IsConstructedInParentProcess()) {
+ return PDocAccessibleChild::SendRoleChangedEvent(aRole);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedRoleChanged>(this, aRole));
+ return true;
+}
+
+bool
+DocAccessibleChild::ConstructChildDocInParentProcess(
+ DocAccessibleChild* aNewChildDoc,
+ uint64_t aUniqueID, uint32_t aMsaaID)
+{
+ if (IsConstructedInParentProcess()) {
+ // We may send the constructor immediately
+ auto tabChild = static_cast<dom::TabChild*>(Manager());
+ MOZ_ASSERT(tabChild);
+ bool result = tabChild->SendPDocAccessibleConstructor(aNewChildDoc, this,
+ aUniqueID, aMsaaID,
+ IAccessibleHolder());
+ if (result) {
+ aNewChildDoc->SetConstructedInParentProcess();
+ }
+ return result;
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedChildDocConstructor>(aNewChildDoc, this,
+ aUniqueID, aMsaaID));
+ return true;
+}
+
+bool
+DocAccessibleChild::SendBindChildDoc(DocAccessibleChild* aChildDoc,
+ const uint64_t& aNewParentID)
+{
+ if (IsConstructedInParentProcess()) {
+ return DocAccessibleChildBase::SendBindChildDoc(aChildDoc, aNewParentID);
+ }
+
+ PushDeferredEvent(MakeUnique<SerializedBindChildDoc>(this, aChildDoc,
+ aNewParentID));
+ return true;
}
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/win/DocAccessibleChild.h
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -4,34 +4,323 @@
* 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/. */
#ifndef mozilla_a11y_DocAccessibleChild_h
#define mozilla_a11y_DocAccessibleChild_h
#include "mozilla/a11y/COMPtrTypes.h"
#include "mozilla/a11y/DocAccessibleChildBase.h"
+#include "mozilla/dom/TabChild.h"
#include "mozilla/mscom/Ptr.h"
namespace mozilla {
namespace a11y {
/*
* These objects handle content side communication for an accessible document,
* and their lifetime is the same as the document they represent.
*/
class DocAccessibleChild : public DocAccessibleChildBase
{
public:
explicit DocAccessibleChild(DocAccessible* aDoc);
~DocAccessibleChild();
- void SendCOMProxy(const IAccessibleHolder& aProxy);
+ virtual void Shutdown() override;
+
+ virtual ipc::IPCResult
+ RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
+ virtual ipc::IPCResult
+ RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
+ const IAccessibleHolder& aEmulatedWindowCOMProxy) override;
+
+ HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
+ IAccessible* GetEmulatedWindowIAccessible() const { return mEmulatedWindowProxy.get(); }
+
IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }
+ bool SendEvent(const uint64_t& aID, const uint32_t& type);
+ bool SendHideEvent(const uint64_t& aRootID, const bool& aFromUser);
+ bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState,
+ const bool& aEnabled);
+ bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset);
+ bool SendTextChangeEvent(const uint64_t& aID, const nsString& aStr,
+ const int32_t& aStart, const uint32_t& aLen,
+ const bool& aIsInsert, const bool& aFromUser);
+ bool SendSelectionEvent(const uint64_t& aID, const uint64_t& aWidgetID,
+ const uint32_t& aType);
+ bool SendRoleChangedEvent(const uint32_t& aRole);
+
+ bool ConstructChildDocInParentProcess(DocAccessibleChild* aNewChildDoc,
+ uint64_t aUniqueID, uint32_t aMsaaID);
+
+ bool SendBindChildDoc(DocAccessibleChild* aChildDoc,
+ const uint64_t& aNewParentID);
+
+protected:
+ virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) override;
+
private:
+ void RemoveDeferredConstructor();
+
+ bool IsConstructedInParentProcess() const { return mIsRemoteConstructed; }
+ void SetConstructedInParentProcess() { mIsRemoteConstructed = true; }
+
+ /**
+ * DocAccessibleChild should not fire events until it has asynchronously
+ * received the COM proxy for its parent. OTOH, content a11y may still be
+ * attempting to fire events during this window of time. If this object does
+ * not yet have its parent proxy, instead of immediately sending the events to
+ * our parent, we enqueue them to mDeferredEvents. As soon as
+ * RecvParentCOMProxy is called, we play back mDeferredEvents.
+ */
+ struct DeferredEvent
+ {
+ void Dispatch()
+ {
+ Dispatch(mTarget);
+ }
+
+ virtual ~DeferredEvent() {}
+
+ protected:
+ explicit DeferredEvent(DocAccessibleChild* aTarget)
+ : mTarget(aTarget)
+ {}
+
+ virtual void Dispatch(DocAccessibleChild* aIPCDoc) = 0;
+
+ private:
+ DocAccessibleChild* mTarget;
+ };
+
+ void PushDeferredEvent(UniquePtr<DeferredEvent> aEvent);
+
+ struct SerializedShow final : public DeferredEvent
+ {
+ SerializedShow(DocAccessibleChild* aTarget,
+ ShowEventData& aEventData, bool aFromUser)
+ : DeferredEvent(aTarget)
+ , mEventData(aEventData.ID(), aEventData.Idx(), nsTArray<AccessibleData>())
+ , mFromUser(aFromUser)
+ {
+ // Since IPDL doesn't generate a move constructor for ShowEventData,
+ // we move NewTree manually (ugh). We still construct with an empty
+ // NewTree above so that the compiler catches any changes made to the
+ // ShowEventData structure in IPDL.
+ mEventData.NewTree() = Move(aEventData.NewTree());
+ }
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendShowEvent(mEventData, mFromUser);
+ }
+
+ ShowEventData mEventData;
+ bool mFromUser;
+ };
+
+ struct SerializedHide final : public DeferredEvent
+ {
+ SerializedHide(DocAccessibleChild* aTarget, uint64_t aRootID, bool aFromUser)
+ : DeferredEvent(aTarget)
+ , mRootID(aRootID)
+ , mFromUser(aFromUser)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendHideEvent(mRootID, mFromUser);
+ }
+
+ uint64_t mRootID;
+ bool mFromUser;
+ };
+
+ struct SerializedStateChange final : public DeferredEvent
+ {
+ SerializedStateChange(DocAccessibleChild* aTarget, uint64_t aID,
+ uint64_t aState, bool aEnabled)
+ : DeferredEvent(aTarget)
+ , mID(aID)
+ , mState(aState)
+ , mEnabled(aEnabled)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendStateChangeEvent(mID, mState, mEnabled);
+ }
+
+ uint64_t mID;
+ uint64_t mState;
+ bool mEnabled;
+ };
+
+ struct SerializedCaretMove final : public DeferredEvent
+ {
+ SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
+ int32_t aOffset)
+ : DeferredEvent(aTarget)
+ , mID(aID)
+ , mOffset(aOffset)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendCaretMoveEvent(mID, mOffset);
+ }
+
+ uint64_t mID;
+ int32_t mOffset;
+ };
+
+ struct SerializedTextChange final : public DeferredEvent
+ {
+ SerializedTextChange(DocAccessibleChild* aTarget, uint64_t aID,
+ const nsString& aStr, int32_t aStart, uint32_t aLen,
+ bool aIsInsert, bool aFromUser)
+ : DeferredEvent(aTarget)
+ , mID(aID)
+ , mStr(aStr)
+ , mStart(aStart)
+ , mLen(aLen)
+ , mIsInsert(aIsInsert)
+ , mFromUser(aFromUser)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendTextChangeEvent(mID, mStr, mStart, mLen, mIsInsert,
+ mFromUser);
+ }
+
+ uint64_t mID;
+ nsString mStr;
+ int32_t mStart;
+ uint32_t mLen;
+ bool mIsInsert;
+ bool mFromUser;
+ };
+
+ struct SerializedSelection final : public DeferredEvent
+ {
+ SerializedSelection(DocAccessibleChild* aTarget, uint64_t aID,
+ uint64_t aWidgetID, uint32_t aType)
+ : DeferredEvent(aTarget)
+ , mID(aID)
+ , mWidgetID(aWidgetID)
+ , mType(aType)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendSelectionEvent(mID, mWidgetID, mType);
+ }
+
+ uint64_t mID;
+ uint64_t mWidgetID;
+ uint32_t mType;
+ };
+
+ struct SerializedRoleChanged final : public DeferredEvent
+ {
+ explicit SerializedRoleChanged(DocAccessibleChild* aTarget, uint32_t aRole)
+ : DeferredEvent(aTarget)
+ , mRole(aRole)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendRoleChangedEvent(mRole);
+ }
+
+ uint32_t mRole;
+ };
+
+ struct SerializedEvent final : public DeferredEvent
+ {
+ SerializedEvent(DocAccessibleChild* aTarget, uint64_t aID, uint32_t aType)
+ : DeferredEvent(aTarget)
+ , mID(aID)
+ , mType(aType)
+ {}
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ Unused << aIPCDoc->SendEvent(mID, mType);
+ }
+
+ uint64_t mID;
+ uint32_t mType;
+ };
+
+ struct SerializedChildDocConstructor final : public DeferredEvent
+ {
+ SerializedChildDocConstructor(DocAccessibleChild* aIPCDoc,
+ DocAccessibleChild* aParentIPCDoc,
+ uint64_t aUniqueID, uint32_t aMsaaID)
+ : DeferredEvent(aParentIPCDoc)
+ , mIPCDoc(aIPCDoc)
+ , mUniqueID(aUniqueID)
+ , mMsaaID(aMsaaID)
+ {}
+
+ void Dispatch(DocAccessibleChild* aParentIPCDoc) override
+ {
+ auto tabChild = static_cast<dom::TabChild*>(aParentIPCDoc->Manager());
+ MOZ_ASSERT(tabChild);
+ Unused << tabChild->SendPDocAccessibleConstructor(mIPCDoc, aParentIPCDoc,
+ mUniqueID, mMsaaID,
+ IAccessibleHolder());
+ mIPCDoc->SetConstructedInParentProcess();
+ }
+
+ DocAccessibleChild* mIPCDoc;
+ uint64_t mUniqueID;
+ uint32_t mMsaaID;
+ };
+
+ friend struct SerializedChildDocConstructor;
+
+ struct SerializedBindChildDoc final : public DeferredEvent
+ {
+ SerializedBindChildDoc(DocAccessibleChild* aParentDoc,
+ DocAccessibleChild* aChildDoc, uint64_t aNewParentID)
+ : DeferredEvent(aParentDoc)
+ , mChildDoc(aChildDoc)
+ , mNewParentID(aNewParentID)
+ {}
+
+ void Dispatch(DocAccessibleChild* aParentIPCDoc) override
+ {
+ Unused << aParentIPCDoc->SendBindChildDoc(mChildDoc, mNewParentID);
+ }
+
+ DocAccessibleChild* mChildDoc;
+ uint64_t mNewParentID;
+ };
+
+ struct SerializedShutdown final : public DeferredEvent
+ {
+ explicit SerializedShutdown(DocAccessibleChild* aTarget)
+ : DeferredEvent(aTarget)
+ {
+ }
+
+ void Dispatch(DocAccessibleChild* aIPCDoc) override
+ {
+ aIPCDoc->Shutdown();
+ }
+ };
+
+ bool mIsRemoteConstructed;
mscom::ProxyUniquePtr<IAccessible> mParentProxy;
+ mscom::ProxyUniquePtr<IAccessible> mEmulatedWindowProxy;
+ nsTArray<UniquePtr<DeferredEvent>> mDeferredEvents;
+ HWND mEmulatedWindowHandle;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_DocAccessibleChild_h
--- a/accessible/ipc/win/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -2,17 +2,17 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
include protocol PFileDescriptorSet;
include protocol PBrowser;
-using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/COMPtrTypes.h";
+using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace a11y {
struct AccessibleData
{
uint64_t ID;
@@ -60,19 +60,18 @@ parent:
* Tell the parent document to bind the existing document as a new child
* document.
*/
async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
sync GetWindowedPluginIAccessible(WindowsHandle aHwnd)
returns (IAccessibleHolder aPluginCOMProxy);
- // For now we'll add the command to send the proxy here. This might move to
- // PDocAccessible constructor in PBrowser.
- sync COMProxy(IAccessibleHolder aDocCOMProxy)
- returns(IAccessibleHolder aParentCOMProxy);
+child:
+ async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
+ async EmulatedWindow(WindowsHandle aEmulatedWindowHandle,
+ IAccessibleHolder aEmulatedWindowCOMProxy);
-child:
async __delete__();
};
}
}
--- a/accessible/ipc/win/PlatformChild.cpp
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -41,20 +41,28 @@ static const mozilla::mscom::ArrayData s
// Type libraries are thread-neutral, so we can register those from any
// apartment. OTOH, proxies must be registered from within the apartment where
// we intend to instantiate them. Therefore RegisterProxy() must be called
// via EnsureMTA.
PlatformChild::PlatformChild()
: mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
mozilla::mscom::RegistrationFlags::eUseSystemDirectory))
, mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb"))
+ , mSdnTypelib(mozilla::mscom::RegisterTypelib(L"AccessibleMarshal.dll"))
{
mozilla::mscom::InterceptorLog::Init();
mozilla::mscom::RegisterArrayData(sPlatformChildArrayData);
+
+ UniquePtr<mozilla::mscom::RegisteredProxy> customProxy;
+ mozilla::mscom::EnsureMTA([&customProxy]() -> void {
+ customProxy = Move(mozilla::mscom::RegisterProxy());
+ });
+ mCustomProxy = Move(customProxy);
+
UniquePtr<mozilla::mscom::RegisteredProxy> ia2Proxy;
mozilla::mscom::EnsureMTA([&ia2Proxy]() -> void {
ia2Proxy = Move(mozilla::mscom::RegisterProxy(L"ia2marshal.dll"));
});
mIA2Proxy = Move(ia2Proxy);
}
} // namespace a11y
--- a/accessible/ipc/win/PlatformChild.h
+++ b/accessible/ipc/win/PlatformChild.h
@@ -18,18 +18,20 @@ public:
PlatformChild();
PlatformChild(PlatformChild&) = delete;
PlatformChild(PlatformChild&&) = delete;
PlatformChild& operator=(PlatformChild&) = delete;
PlatformChild& operator=(PlatformChild&&) = delete;
private:
+ UniquePtr<mozilla::mscom::RegisteredProxy> mCustomProxy;
UniquePtr<mozilla::mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mozilla::mscom::RegisteredProxy> mAccTypelib;
UniquePtr<mozilla::mscom::RegisteredProxy> mMiscTypelib;
+ UniquePtr<mozilla::mscom::RegisteredProxy> mSdnTypelib;
};
} // namespace mozilla
} // namespace a11y
#endif // mozilla_a11y_PlatformChild_h
--- a/accessible/ipc/win/ProxyAccessible.cpp
+++ b/accessible/ipc/win/ProxyAccessible.cpp
@@ -1,17 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "Accessible2.h"
#include "ProxyAccessible.h"
+#include "ia2AccessibleRelation.h"
#include "ia2AccessibleValue.h"
+#include "IGeckoCustom.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "DocAccessible.h"
#include "mozilla/a11y/DocManager.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/Unused.h"
#include "mozilla/a11y/Platform.h"
#include "RelationType.h"
@@ -62,16 +64,34 @@ struct InterfaceIID<IAccessibleValue>
};
template<>
struct InterfaceIID<IAccessibleText>
{
static REFIID Value() { return IID_IAccessibleText; }
};
+template<>
+struct InterfaceIID<IAccessibleHyperlink>
+{
+ static REFIID Value() { return IID_IAccessibleHyperlink; }
+};
+
+template<>
+struct InterfaceIID<IGeckoCustom>
+{
+ static REFIID Value() { return IID_IGeckoCustom; }
+};
+
+template<>
+struct InterfaceIID<IAccessible2_2>
+{
+ static REFIID Value() { return IID_IAccessible2_2; }
+};
+
/**
* Get the COM proxy for this proxy accessible and QueryInterface it with the
* correct IID
*/
template<typename Interface>
static already_AddRefed<Interface>
QueryInterface(const ProxyAccessible* aProxy)
{
@@ -84,16 +104,33 @@ QueryInterface(const ProxyAccessible* aP
if (FAILED(acc->QueryInterface(InterfaceIID<Interface>::Value(),
(void**)getter_AddRefs(acc2)))) {
return nullptr;
}
return acc2.forget();
}
+static ProxyAccessible*
+GetProxyFor(DocAccessibleParent* aDoc, IUnknown* aCOMProxy)
+{
+ RefPtr<IGeckoCustom> custom;
+ if (FAILED(aCOMProxy->QueryInterface(IID_IGeckoCustom,
+ (void**) getter_AddRefs(custom)))) {
+ return nullptr;
+ }
+
+ uint64_t id;
+ if (FAILED(custom->get_ID(&id))) {
+ return nullptr;
+ }
+
+ return aDoc->GetAccessible(id);
+}
+
void
ProxyAccessible::Name(nsString& aName) const
{
aName.Truncate();
RefPtr<IAccessible> acc;
if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
return;
}
@@ -120,16 +157,33 @@ ProxyAccessible::Value(nsString& aValue)
HRESULT hr = acc->get_accValue(kChildIdSelf, &result);
_bstr_t resultWrap(result, false);
if (FAILED(hr)) {
return;
}
aValue = (wchar_t*)resultWrap;
}
+double
+ProxyAccessible::Step()
+{
+ RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
+ if (!custom) {
+ return 0;
+ }
+
+ double increment;
+ HRESULT hr = custom->get_minimumIncrement(&increment);
+ if (FAILED(hr)) {
+ return 0;
+ }
+
+ return increment;
+}
+
void
ProxyAccessible::Description(nsString& aDesc) const
{
aDesc.Truncate();
RefPtr<IAccessible> acc;
if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
return;
}
@@ -141,28 +195,27 @@ ProxyAccessible::Description(nsString& a
return;
}
aDesc = (wchar_t*)resultWrap;
}
uint64_t
ProxyAccessible::State() const
{
- uint64_t state = 0;
- RefPtr<IAccessible> acc;
- if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
- return state;
+ RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
+ if (!custom) {
+ return 0;
}
- VARIANT varState;
- HRESULT hr = acc->get_accState(kChildIdSelf, &varState);
+ uint64_t state;
+ HRESULT hr = custom->get_mozState(&state);
if (FAILED(hr)) {
- return state;
+ return 0;
}
- return uint64_t(varState.lVal);
+ return state;
}
nsIntRect
ProxyAccessible::Bounds()
{
nsIntRect rect;
RefPtr<IAccessible> acc;
@@ -281,16 +334,17 @@ ConvertBSTRAttributesToArray(const nsASt
tokens[eName].Truncate();
tokens[eValue].Truncate();
++itr;
continue;
default:
break;
}
tokens[state] += *itr;
+ ++itr;
}
return true;
}
void
ProxyAccessible::Attributes(nsTArray<Attribute>* aAttrs) const
{
aAttrs->Clear();
@@ -312,16 +366,54 @@ ProxyAccessible::Attributes(nsTArray<Att
return;
}
ConvertBSTRAttributesToArray(nsDependentString((wchar_t*)attrs,
attrsWrap.length()),
aAttrs);
}
+nsTArray<ProxyAccessible*>
+ProxyAccessible::RelationByType(RelationType aType) const
+{
+ RefPtr<IAccessible2_2> acc = QueryInterface<IAccessible2_2>(this);
+ if (!acc) {
+ nsTArray<ProxyAccessible*>();
+ }
+
+ _bstr_t relationType;
+ for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
+ if (aType == sRelationTypePairs[idx].first) {
+ relationType = sRelationTypePairs[idx].second;
+ break;
+ }
+ }
+
+ if (!relationType) {
+ nsTArray<ProxyAccessible*>();
+ }
+
+ IUnknown** targets;
+ long nTargets = 0;
+ HRESULT hr = acc->get_relationTargetsOfType(relationType, 0, &targets, &nTargets);
+ if (FAILED(hr)) {
+ nsTArray<ProxyAccessible*>();
+ }
+
+ nsTArray<ProxyAccessible*> proxies;
+ for (long idx = 0; idx < nTargets; idx++) {
+ IUnknown* target = targets[idx];
+ proxies.AppendElement(GetProxyFor(Document(), target));
+ target->Release();
+ }
+ CoTaskMemFree(targets);
+
+ return Move(proxies);
+}
+
double
ProxyAccessible::CurValue()
{
RefPtr<IAccessibleValue> acc = QueryInterface<IAccessibleValue>(this);
if (!acc) {
return UnspecifiedNaN<double>();
}
@@ -590,10 +682,109 @@ ProxyAccessible::ScrollSubstringToPoint(
acc->scrollSubstringToPoint(static_cast<long>(aStartOffset),
static_cast<long>(aEndOffset),
coordType,
static_cast<long>(aX),
static_cast<long>(aY));
}
+uint32_t
+ProxyAccessible::StartOffset(bool* aOk)
+{
+ RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+ if (!acc) {
+ *aOk = false;
+ return 0;
+ }
+
+ long startOffset;
+ *aOk = SUCCEEDED(acc->get_startIndex(&startOffset));
+ return static_cast<uint32_t>(startOffset);
+}
+
+uint32_t
+ProxyAccessible::EndOffset(bool* aOk)
+{
+ RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+ if (!acc) {
+ *aOk = false;
+ return 0;
+ }
+
+ long endOffset;
+ *aOk = SUCCEEDED(acc->get_endIndex(&endOffset));
+ return static_cast<uint32_t>(endOffset);
+}
+
+bool
+ProxyAccessible::IsLinkValid()
+{
+ RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+ if (!acc) {
+ return false;
+ }
+
+ boolean valid;
+ if (FAILED(acc->get_valid(&valid))) {
+ return false;
+ }
+
+ return valid;
+}
+
+uint32_t
+ProxyAccessible::AnchorCount(bool* aOk)
+{
+ *aOk = false;
+ RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
+ if (!custom) {
+ return 0;
+ }
+
+ long count;
+ if (FAILED(custom->get_anchorCount(&count))) {
+ return 0;
+ }
+
+ *aOk = true;
+ return count;
+}
+
+ProxyAccessible*
+ProxyAccessible::AnchorAt(uint32_t aIdx)
+{
+ RefPtr<IAccessibleHyperlink> link = QueryInterface<IAccessibleHyperlink>(this);
+ if (!link) {
+ return nullptr;
+ }
+
+ VARIANT anchor;
+ if (FAILED(link->get_anchor(aIdx, &anchor))) {
+ return nullptr;
+ }
+
+ MOZ_ASSERT(anchor.vt == VT_UNKNOWN);
+ ProxyAccessible* proxyAnchor = GetProxyFor(Document(), anchor.punkVal);
+ anchor.punkVal->Release();
+ return proxyAnchor;
+}
+
+void
+ProxyAccessible::DOMNodeID(nsString& aID)
+{
+ aID.Truncate();
+ RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
+ if (!custom) {
+ return;
+ }
+
+ BSTR result;
+ HRESULT hr = custom->get_DOMNodeID(&result);
+ _bstr_t resultWrap(result, false);
+ if (FAILED(hr)) {
+ return;
+ }
+ aID = (wchar_t*)resultWrap;
+}
+
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/win/ProxyAccessible.h
+++ b/accessible/ipc/win/ProxyAccessible.h
@@ -34,25 +34,24 @@ public:
~ProxyAccessible()
{
MOZ_COUNT_DTOR(ProxyAccessible);
}
#include "mozilla/a11y/ProxyAccessibleShared.h"
bool GetCOMInterface(void** aOutAccessible) const;
+ void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible)
+ { mCOMProxy = aIAccessible; }
protected:
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
: ProxyAccessibleBase(aThisAsDoc)
{ MOZ_COUNT_CTOR(ProxyAccessible); }
- void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible)
- { mCOMProxy = aIAccessible; }
-
private:
RefPtr<IAccessible> mCOMProxy;
};
}
}
#endif
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -10,16 +10,20 @@
const {utils: Cu, interfaces: Ci} = Components;
this.EXPORTED_SYMBOLS = ['AccessFu']; // jshint ignore:line
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+if (Utils.MozBuildApp === 'mobile/android') {
+ Cu.import('resource://gre/modules/Messaging.jsm');
+}
+
const ACCESSFU_DISABLE = 0; // jshint ignore:line
const ACCESSFU_ENABLE = 1;
const ACCESSFU_AUTO = 2;
const SCREENREADER_SETTING = 'accessibility.screenreader';
const QUICKNAV_MODES_PREF = 'accessibility.accessfu.quicknav_modes';
const QUICKNAV_INDEX_PREF = 'accessibility.accessfu.quicknav_index';
@@ -27,31 +31,19 @@ this.AccessFu = { // jshint ignore:line
/**
* Initialize chrome-layer accessibility functionality.
* If accessibility is enabled on the platform, then a special accessibility
* mode is started.
*/
attach: function attach(aWindow) {
Utils.init(aWindow);
- try {
- Services.androidBridge.dispatch('Accessibility:Ready');
- Services.obs.addObserver(this, 'Accessibility:Settings', false);
- } catch (x) {
- // Not on Android
- if (aWindow.navigator.mozSettings) {
- let lock = aWindow.navigator.mozSettings.createLock();
- let req = lock.get(SCREENREADER_SETTING);
- req.addEventListener('success', () => {
- this._systemPref = req.result[SCREENREADER_SETTING];
- this._enableOrDisable();
- });
- aWindow.navigator.mozSettings.addObserver(
- SCREENREADER_SETTING, this.handleEvent);
- }
+ if (Utils.MozBuildApp === 'mobile/android') {
+ EventDispatcher.instance.dispatch('Accessibility:Ready');
+ EventDispatcher.instance.registerListener(this, 'Accessibility:Settings');
}
this._activatePref = new PrefCache(
'accessibility.accessfu.activate', this._enableOrDisable.bind(this));
this._enableOrDisable();
},
@@ -59,20 +51,17 @@ this.AccessFu = { // jshint ignore:line
* Shut down chrome-layer accessibility functionality from the outside.
*/
detach: function detach() {
// Avoid disabling twice.
if (this._enabled) {
this._disable();
}
if (Utils.MozBuildApp === 'mobile/android') {
- Services.obs.removeObserver(this, 'Accessibility:Settings');
- } else if (Utils.win.navigator.mozSettings) {
- Utils.win.navigator.mozSettings.removeObserver(
- SCREENREADER_SETTING, this.handleEvent);
+ EventDispatcher.instance.unregisterListener(this, 'Accessibility:Settings');
}
delete this._activatePref;
Utils.uninit();
},
/**
* A lazy getter for event handler that binds the scope to AccessFu object.
*/
@@ -128,26 +117,31 @@ this.AccessFu = { // jshint ignore:line
this._notifyOutputPref =
new PrefCache('accessibility.accessfu.notify_output');
this.Input.start();
Output.start();
PointerAdapter.start();
+ if (Utils.MozBuildApp === 'mobile/android') {
+ EventDispatcher.instance.registerListener(this, [
+ 'Accessibility:ActivateObject',
+ 'Accessibility:Focus',
+ 'Accessibility:LongPress',
+ 'Accessibility:MoveByGranularity',
+ 'Accessibility:NextObject',
+ 'Accessibility:PreviousObject',
+ 'Accessibility:ScrollBackward',
+ 'Accessibility:ScrollForward',
+ ]);
+ }
+
Services.obs.addObserver(this, 'remote-browser-shown', false);
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
- Services.obs.addObserver(this, 'Accessibility:NextObject', false);
- Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
- Services.obs.addObserver(this, 'Accessibility:Focus', false);
- Services.obs.addObserver(this, 'Accessibility:ActivateObject', false);
- Services.obs.addObserver(this, 'Accessibility:LongPress', false);
- Services.obs.addObserver(this, 'Accessibility:ScrollForward', false);
- Services.obs.addObserver(this, 'Accessibility:ScrollBackward', false);
- Services.obs.addObserver(this, 'Accessibility:MoveByGranularity', false);
Utils.win.addEventListener('TabOpen', this);
Utils.win.addEventListener('TabClose', this);
Utils.win.addEventListener('TabSelect', this);
if (this.readyCallback) {
this.readyCallback();
delete this.readyCallback;
}
@@ -177,24 +171,29 @@ this.AccessFu = { // jshint ignore:line
PointerAdapter.stop();
Utils.win.removeEventListener('TabOpen', this);
Utils.win.removeEventListener('TabClose', this);
Utils.win.removeEventListener('TabSelect', this);
Services.obs.removeObserver(this, 'remote-browser-shown');
Services.obs.removeObserver(this, 'inprocess-browser-shown');
- Services.obs.removeObserver(this, 'Accessibility:NextObject');
- Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
- Services.obs.removeObserver(this, 'Accessibility:Focus');
- Services.obs.removeObserver(this, 'Accessibility:ActivateObject');
- Services.obs.removeObserver(this, 'Accessibility:LongPress');
- Services.obs.removeObserver(this, 'Accessibility:ScrollForward');
- Services.obs.removeObserver(this, 'Accessibility:ScrollBackward');
- Services.obs.removeObserver(this, 'Accessibility:MoveByGranularity');
+
+ if (Utils.MozBuildApp === 'mobile/android') {
+ EventDispatcher.instance.unregisterListener(this, [
+ 'Accessibility:ActivateObject',
+ 'Accessibility:Focus',
+ 'Accessibility:LongPress',
+ 'Accessibility:MoveByGranularity',
+ 'Accessibility:NextObject',
+ 'Accessibility:PreviousObject',
+ 'Accessibility:ScrollBackward',
+ 'Accessibility:ScrollForward',
+ ]);
+ }
delete this._quicknavModesPref;
delete this._notifyOutputPref;
if (this.doneCallback) {
this.doneCallback();
delete this.doneCallback;
}
@@ -296,53 +295,57 @@ this.AccessFu = { // jshint ignore:line
_handleMessageManager: function _handleMessageManager(aMessageManager) {
if (this._enabled) {
this._addMessageListeners(aMessageManager);
}
this._loadFrameScript(aMessageManager);
},
- observe: function observe(aSubject, aTopic, aData) {
- switch (aTopic) {
+ onEvent: function (event, data, callback) {
+ switch (event) {
case 'Accessibility:Settings':
- this._systemPref = JSON.parse(aData).enabled;
+ this._systemPref = data.enabled;
this._enableOrDisable();
break;
case 'Accessibility:NextObject':
- case 'Accessibility:PreviousObject':
- {
- let rule = aData ?
- aData.substr(0, 1).toUpperCase() + aData.substr(1).toLowerCase() :
+ case 'Accessibility:PreviousObject': {
+ let rule = data ?
+ data.rule.substr(0, 1).toUpperCase() + data.rule.substr(1).toLowerCase() :
'Simple';
- let method = aTopic.replace(/Accessibility:(\w+)Object/, 'move$1');
+ let method = event.replace(/Accessibility:(\w+)Object/, 'move$1');
this.Input.moveCursor(method, rule, 'gesture');
break;
}
case 'Accessibility:ActivateObject':
- this.Input.activateCurrent(JSON.parse(aData));
+ this.Input.activateCurrent(data);
break;
case 'Accessibility:LongPress':
this.Input.sendContextMenuMessage();
break;
case 'Accessibility:ScrollForward':
this.Input.androidScroll('forward');
break;
case 'Accessibility:ScrollBackward':
this.Input.androidScroll('backward');
break;
case 'Accessibility:Focus':
- this._focused = JSON.parse(aData);
+ this._focused = data.gainFocus;
if (this._focused) {
this.autoMove({ forcePresent: true, noOpIfOnScreen: true });
}
break;
case 'Accessibility:MoveByGranularity':
- this.Input.moveByGranularity(JSON.parse(aData));
+ this.Input.moveByGranularity(data);
break;
+ }
+ },
+
+ observe: function observe(aSubject, aTopic, aData) {
+ switch (aTopic) {
case 'remote-browser-shown':
case 'inprocess-browser-shown':
{
// Ignore notifications that aren't from a Browser
let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
if (!frameLoader.ownerIsMozBrowserFrame) {
return;
}
@@ -577,35 +580,22 @@ var Output = {
if (highlightBox) {
highlightBox.classList.remove('show');
}
break;
}
}
},
- get androidBridge() {
- delete this.androidBridge;
- if (Utils.MozBuildApp === 'mobile/android') {
- this.androidBridge = Services.androidBridge;
- } else {
- this.androidBridge = null;
- }
- return this.androidBridge;
- },
-
Android: function Android(aDetails, aBrowser) {
const ANDROID_VIEW_TEXT_CHANGED = 0x10;
const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
- if (!this.androidBridge) {
- return;
- }
-
for (let androidEvent of aDetails) {
+ androidEvent.type = 'Accessibility:Event';
if (androidEvent.bounds) {
androidEvent.bounds = AccessFu.adjustContentBounds(
androidEvent.bounds, aBrowser);
}
switch(androidEvent.eventType) {
case ANDROID_VIEW_TEXT_CHANGED:
androidEvent.brailleOutput = this.brailleState.adjustText(
@@ -615,19 +605,18 @@ var Output = {
androidEvent.brailleOutput = this.brailleState.adjustSelection(
androidEvent.brailleOutput);
break;
default:
androidEvent.brailleOutput = this.brailleState.init(
androidEvent.brailleOutput);
break;
}
- let win = Utils.win;
- let view = win && win.QueryInterface(Ci.nsIAndroidView);
- view.dispatch('Accessibility:Event', androidEvent);
+
+ Utils.win.WindowEventDispatcher.sendRequest(androidEvent);
}
},
Braille: function Braille(aDetails) {
Logger.debug('Braille output: ' + aDetails.output);
}
};
@@ -813,19 +802,17 @@ var Input = {
return;
} else {
target.blur();
}
}
if (Utils.MozBuildApp == 'mobile/android') {
// Return focus to native Android browser chrome.
- let win = Utils.win;
- let view = win && win.QueryInterface(Ci.nsIAndroidView);
- view.dispatch('ToggleChrome:Focus');
+ Utils.win.WindowEventDispatcher.dispatch('ToggleChrome:Focus');
}
break;
case aEvent.DOM_VK_RETURN:
if (this.editState.editing) {
return;
}
this.activateCurrent();
break;
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -111,17 +111,17 @@ this.EventManager.prototype = {
{
// the target could be an element, document or window
let window = null;
if (aEvent.target instanceof Ci.nsIDOMWindow)
window = aEvent.target;
else if (aEvent.target instanceof Ci.nsIDOMDocument)
window = aEvent.target.defaultView;
else if (aEvent.target instanceof Ci.nsIDOMElement)
- window = aEvent.target.ownerDocument.defaultView;
+ window = aEvent.target.ownerGlobal;
this.present(Presentation.viewportChanged(window));
break;
}
}
} catch (x) {
Logger.logException(x, 'Error handling DOM event');
}
},
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -310,17 +310,17 @@ AndroidPresenter.prototype.pivotChanged
};
AndroidPresenter.prototype.actionInvoked =
function AndroidPresenter_actionInvoked(aObject, aActionName) {
let state = Utils.getState(aObject);
// Checkable objects use TalkBack's text derived from the event state,
// so we don't populate the text here.
- let text = '';
+ let text = null;
if (!state.contains(States.CHECKABLE)) {
text = Utils.localize(UtteranceGenerator.genForAction(aObject,
aActionName));
}
return {
type: this.type,
details: [{
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -1,15 +1,15 @@
/* 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/. */
/* global Components, XPCOMUtils, Services, PluralForm, Logger, Rect, Utils,
States, Relations, Roles, dump, Events, PivotContext, PrefCache */
-/* exported Utils, Logger, PivotContext, PrefCache, SettingCache */
+/* exported Utils, Logger, PivotContext, PrefCache */
'use strict';
const {classes: Cc, utils: Cu, interfaces: Ci} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Services', // jshint ignore:line
'resource://gre/modules/Services.jsm');
@@ -21,18 +21,17 @@ XPCOMUtils.defineLazyModuleGetter(this,
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Relations', // jshint ignore:line
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States', // jshint ignore:line
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm', // jshint ignore:line
'resource://gre/modules/PluralForm.jsm');
-this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache', // jshint ignore:line
- 'SettingCache'];
+this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache']; // jshint ignore:line
this.Utils = { // jshint ignore:line
_buildAppMap: {
'{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
'{d1bfe7d9-c01e-4237-998b-7b5f960a4314}': 'graphene',
'{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser',
'{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
'{a23983c0-fd0e-11dc-95ff-0800200c9a66}': 'mobile/xul'
@@ -1069,46 +1068,8 @@ PrefCache.prototype = {
Logger.logException(x);
}
}
},
QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference])
};
-
-this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) { // jshint ignore:line
- this.value = aOptions.defaultValue;
- let runCallback = () => {
- if (aCallback) {
- aCallback(aName, this.value);
- if (aOptions.callbackOnce) {
- runCallback = () => {};
- }
- }
- };
-
- let settings = Utils.win.navigator.mozSettings;
- if (!settings) {
- if (aOptions.callbackNow) {
- runCallback();
- }
- return;
- }
-
-
- let lock = settings.createLock();
- let req = lock.get(aName);
-
- req.addEventListener('success', () => {
- this.value = req.result[aName] === undefined ?
- aOptions.defaultValue : req.result[aName];
- if (aOptions.callbackNow) {
- runCallback();
- }
- });
-
- settings.addObserver(aName,
- (evt) => {
- this.value = evt.settingValue;
- runCallback();
- });
-};
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -8,16 +8,17 @@
#import "MacUtils.h"
#import "mozView.h"
#include "Accessible-inl.h"
#include "nsAccUtils.h"
#include "nsIAccessibleRelation.h"
#include "nsIAccessibleEditableText.h"
#include "nsIPersistentProperties2.h"
+#include "DocAccessibleParent.h"
#include "Relation.h"
#include "Role.h"
#include "RootAccessible.h"
#include "TableAccessible.h"
#include "TableCellAccessible.h"
#include "mozilla/a11y/PDocAccessible.h"
#include "OuterDocAccessible.h"
--- a/accessible/moz.build
+++ b/accessible/moz.build
@@ -29,8 +29,11 @@ if CONFIG['MOZ_XUL']:
DIRS += ['xul']
TEST_DIRS += ['tests/mochitest']
BROWSER_CHROME_MANIFESTS += [
'tests/browser/browser.ini',
'tests/browser/e10s/browser.ini'
]
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Disability Access APIs")
\ No newline at end of file
--- a/accessible/tests/browser/.eslintrc.js
+++ b/accessible/tests/browser/.eslintrc.js
@@ -1,13 +1,13 @@
"use strict";
module.exports = { // eslint-disable-line no-undef
"extends": [
- "../../../testing/mochitest/browser.eslintrc.js"
+ "plugin:mozilla/browser-test"
],
// All globals made available in the test environment.
"globals": {
// Content scripts have global 'content' object
"content": true,
"add_task": true,
--- a/accessible/tests/browser/e10s/browser.ini
+++ b/accessible/tests/browser/e10s/browser.ini
@@ -1,10 +1,9 @@
[DEFAULT]
-skip-if = (e10s && os == 'win') # Bug 1269369: Document loaded event does not fire in Windows
support-files =
events.js
head.js
doc_treeupdate_ariadialog.html
doc_treeupdate_ariaowns.html
doc_treeupdate_imagemap.html
doc_treeupdate_removal.xhtml
doc_treeupdate_visibility.html
@@ -13,16 +12,17 @@ support-files =
!/accessible/tests/mochitest/*.js
!/accessible/tests/mochitest/letters.gif
!/accessible/tests/mochitest/moz.png
# Caching tests
[browser_caching_attributes.js]
[browser_caching_description.js]
[browser_caching_name.js]
+skip-if = e10s && os == 'win' && debug # Bug 1338034, leaks
[browser_caching_relations.js]
[browser_caching_states.js]
[browser_caching_value.js]
# Events tests
[browser_events_caretmove.js]
[browser_events_hide.js]
[browser_events_show.js]
@@ -30,16 +30,17 @@ support-files =
[browser_events_textchange.js]
# Tree update tests
[browser_treeupdate_ariadialog.js]
[browser_treeupdate_ariaowns.js]
[browser_treeupdate_canvas.js]
[browser_treeupdate_cssoverflow.js]
[browser_treeupdate_doc.js]
+skip-if = e10s && os == 'win' # Bug 1288839
[browser_treeupdate_gencontent.js]
[browser_treeupdate_hidden.js]
[browser_treeupdate_imagemap.js]
[browser_treeupdate_list.js]
[browser_treeupdate_list_editabledoc.js]
[browser_treeupdate_listener.js]
[browser_treeupdate_optgroup.js]
[browser_treeupdate_removal.js]
--- a/accessible/tests/browser/e10s/browser_caching_name.js
+++ b/accessible/tests/browser/e10s/browser_caching_name.js
@@ -387,17 +387,17 @@ function* testElmRule(browser, target, r
* @param {[type]} expected expected name value
*/
function* testSubtreeRule(browser, target, rule, expected) {
testName(target.acc, expected);
let onEvent = waitForEvent(EVENT_REORDER, target.id);
yield ContentTask.spawn(browser, target.id, id => {
let elm = content.document.getElementById(id);
while (elm.firstChild) {
- elm.removeChild(elm.firstChild);
+ elm.firstChild.remove();
}
});
yield updateAccessibleIfNeeded(onEvent, target);
}
/**
* Iterate over a list of rules and test accessible names for each one of the
* rules.
--- a/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
@@ -112,18 +112,17 @@ function* testContainer1(browser, accDoc
{ GROUPING: [ ] } // ARIA owned, t1_group
]
};
testAccessibleTree(acc, tree);
/* ================ Remove element ======================================== */
onReorder = waitForEvent(EVENT_REORDER, id);
yield ContentTask.spawn(browser, {}, () =>
- content.document.getElementById('t1_span').parentNode.removeChild(
- content.document.getElementById('t1_span')));
+ content.document.getElementById('t1_span').remove());
yield onReorder;
// subdiv should go away
tree = {
SECTION: [
{ CHECKBUTTON: [ ] }, // explicit, t1_checkbox
{ RADIOBUTTON: [ ] }, // explicit, t1_child3
{ PUSHBUTTON: [ ] }, // ARIA owned, t1_button
--- a/accessible/tests/browser/e10s/browser_treeupdate_doc.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_doc.js
@@ -152,17 +152,17 @@ addAccessibleTask(`
};
testAccessibleTree(iframe, tree);
/* ================= Remove HTML from iframe document ===================== */
reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
yield ContentTask.spawn(browser, {}, () => {
// Remove HTML element.
let docNode = content.document.getElementById('iframe').contentDocument;
- docNode.removeChild(docNode.firstChild);
+ docNode.firstChild.remove();
});
let event = yield reorderEventPromise;
ok(event.accessible instanceof nsIAccessibleDocument,
'Reorder should happen on the document');
tree = {
role: ROLE_DOCUMENT,
children: [ ]
@@ -230,17 +230,17 @@ addAccessibleTask(`
};
testAccessibleTree(iframe, tree);
reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
yield ContentTask.spawn(browser, {}, () => {
let docEl =
content.document.getElementById('iframe').contentDocument.documentElement;
// Remove aftermath of this test before next test starts.
- docEl.removeChild(docEl.firstChild);
+ docEl.firstChild.remove();
});
// Make sure reorder event was fired and that the input was removed.
yield reorderEventPromise;
tree = {
role: ROLE_DOCUMENT,
children: [ ]
};
testAccessibleTree(iframe, tree);
--- a/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
@@ -114,17 +114,17 @@ function* testContainer(browser) {
} ]
};
testAccessibleTree(acc, tree);
/* ================= Remove map =========================================== */
onReorder = waitForEvent(EVENT_REORDER, id);
yield ContentTask.spawn(browser, {}, () => {
let mapNode = content.document.getElementById('map');
- mapNode.parentNode.removeChild(mapNode);
+ mapNode.remove();
});
yield onReorder;
tree = {
SECTION: [
{ GRAPHIC: [ ] }
]
};
@@ -165,12 +165,27 @@ function* testContainer(browser) {
yield onReorder;
tree = {
SECTION: [ ]
};
testAccessibleTree(acc, tree);
}
+function* waitForImageMap(browser, accDoc) {
+ const id = 'imgmap';
+ const acc = findAccessibleChildByID(accDoc, id);
+ if (acc.firstChild) {
+ return;
+ }
+
+ const onReorder = waitForEvent(EVENT_REORDER, id);
+ // Wave over image map
+ yield BrowserTestUtils.synthesizeMouse(`#${id}`, 10, 10,
+ { type: 'mousemove' }, browser);
+ yield onReorder;
+}
+
addAccessibleTask('doc_treeupdate_imagemap.html', function*(browser, accDoc) {
+ yield waitForImageMap(browser, accDoc);
yield testImageMap(browser, accDoc);
yield testContainer(browser);
});
--- a/accessible/tests/browser/e10s/browser_treeupdate_listener.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_listener.js
@@ -21,23 +21,9 @@ addAccessibleTask('<span id="parent"><sp
content.window.dummyListener = () => {};
content.document.getElementById('parent').addEventListener(
'click', content.window.dummyListener);
});
yield onReorder;
let tree = { TEXT: [] };
testAccessibleTree(findAccessibleChildByID(accDoc, 'parent'), tree);
-
- onReorder = waitForEvent(EVENT_REORDER, 'body');
- // Remove an event listener from parent.
- yield ContentTask.spawn(browser, {}, () => {
- content.document.getElementById('parent').removeEventListener(
- 'click', content.window.dummyListener);
- delete content.window.dummyListener;
- });
- yield onReorder;
-
- is(findAccessibleChildByID(accDoc, 'parent'), null,
- 'Check that parent is not accessible.');
- is(findAccessibleChildByID(accDoc, 'child'), null,
- 'Check that child is not accessible.');
});
--- a/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
@@ -51,17 +51,17 @@ addAccessibleTask('<select id="select"><
};
testAccessibleTree(select, tree);
ok(!isDefunct(option1Node), 'option shouldn\'t be defunct');
onEvent = waitForEvent(EVENT_REORDER, 'select');
// Remove grouping from combobox
yield ContentTask.spawn(browser, {}, () => {
let contentSelect = content.document.getElementById('select');
- contentSelect.removeChild(contentSelect.firstChild);
+ contentSelect.firstChild.remove();
});
yield onEvent;
tree = {
COMBOBOX: [ {
COMBOBOX_LIST: [
{ COMBOBOX_OPTION: [] },
{ COMBOBOX_OPTION: [] }
--- a/accessible/tests/crashtests/448064.xhtml
+++ b/accessible/tests/crashtests/448064.xhtml
@@ -27,40 +27,37 @@ function dumpAccessibleNode(aNode, level
msg += " noName ";
}
dump(msg + '\n');
}
function dumpAccessibleTree(aNode, level) {
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
level = level || 0;
dumpAccessibleNode(aNode, level);
try {
var child = aNode.firstChild;
while (child) {
dumpAccessibleTree(child, level + 1);
child = child.nextSibling;
}
} catch (e) {
dump("Error visiting child nodes: " + e + '\n');
}
}
function A(o) {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- var acc = Components.classes['@mozilla.org/accessibilityService;1']
- .getService(Components.interfaces.nsIAccessibilityService);
+ var acc = SpecialPowers.Cc['@mozilla.org/accessibilityService;1']
+ .getService(SpecialPowers.Ci.nsIAccessibilityService);
return acc.getAccessibleFor(o);
}
function beginAccessible() {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
dumpAccessibleTree(A(document),0);
}
setTimeout(beginAccessible, 100);
setTimeout(doe, 200);
function doe() {
document.getElementById('mw_a').appendChild(document.getElementById('mw_b'));
--- a/accessible/tests/mochitest/aom/test_general.html
+++ b/accessible/tests/mochitest/aom/test_general.html
@@ -30,26 +30,78 @@
}
// WebIDL conditional annotations for an interface are evaluated once per
// global, so we need to create an iframe to see the effects of calling
// enablePref().
function createIframe() {
return new Promise((resolve) => {
let iframe = document.createElement("iframe");
- iframe.src = "about:blank";
+ iframe.src = `data:text/html,<html><body>hey</body></html>`;
iframe.onload = () => resolve(iframe.contentDocument);
document.body.appendChild(iframe);
});
}
// Check that the WebIDL is as expected.
function checkImplementation(ifrDoc) {
let anode = ifrDoc.accessibleNode;
ok(anode, "DOM document has accessible node");
is(anode.role, 'document', 'correct role of a document accessible node');
is(anode.DOMNode, ifrDoc, 'correct DOM Node of a document accessible node');
+ // States may differ depending on the document state, for example, if it is
+ // loaded or is loading still.
+ var states = null;
+ switch (anode.states.length) {
+ case 5:
+ states = [
+ 'readonly', 'focusable', 'opaque', 'enabled', 'sensitive'
+ ];
+ break;
+ case 6:
+ states = [
+ 'readonly', 'busy', 'focusable', 'opaque', 'enabled', 'sensitive'
+ ];
+ break;
+ case 7:
+ states = [
+ 'readonly', 'busy', 'focusable', 'opaque', 'stale', 'enabled', 'sensitive'
+ ];
+ break;
+ default:
+ ok(false, 'Unexpected amount of states');
+ }
+ if (states) {
+ for (var i = 0; i < states.length; i++) {
+ is(anode.states[i], states[i], `${states[i]} state is expected at ${i}th index`);
+ }
+ }
+
+ ok(anode.is('document', 'focusable'),
+ 'correct role and state on an accessible node');
+
+ is(anode.get('explicit-name'), 'true',
+ 'correct object attribute value on an accessible node');
+
+ ok(anode.has('explicit-name'),
+ 'object attributes are present');
+
+ var attrs = [ 'explicit-name' ];
+ if (anode.attributes.length > 1) {
+ attrs = [
+ 'margin-left', 'text-align', 'text-indent', 'margin-right',
+ 'tag', 'margin-top', 'margin-bottom', 'display',
+ 'explicit-name'
+ ];
+ }
+
+ is(anode.attributes.length, attrs.length, 'correct number of attributes');
+ for (var i = 0; i < attrs.length; i++) {
+ is(anode.attributes[i], attrs[i],
+ `${attrs[i]} attribute is expected at ${i}th index`);
+ }
+
finish();
}
</script>
</head>
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -28,17 +28,17 @@ function testAbsentAttrs(aAccOrElmOrID,
}
/**
* Test CSS based object attributes.
*/
function testCSSAttrs(aID)
{
var node = document.getElementById(aID);
- var computedStyle = document.defaultView.getComputedStyle(node, "");
+ var computedStyle = document.defaultView.getComputedStyle(node);
var attrs = {
"display": computedStyle.display,
"text-align": computedStyle.textAlign,
"text-indent": computedStyle.textIndent,
"margin-left": computedStyle.marginLeft,
"margin-right": computedStyle.marginRight,
"margin-top": computedStyle.marginTop,
@@ -263,18 +263,18 @@ function fontFamily(aComputedStyle)
* @param aID [in] identifier of accessible
* @param aFontSize [in] font size
* @param aFontWeight [in, optional] kBoldFontWeight or kNormalFontWeight,
* default value is kNormalFontWeight
*/
function buildDefaultTextAttrs(aID, aFontSize, aFontWeight, aFontFamily)
{
var elm = getNode(aID);
- var computedStyle = document.defaultView.getComputedStyle(elm, "");
- var bgColor = computedStyle.backgroundColor == "transparent" ?
+ var computedStyle = document.defaultView.getComputedStyle(elm);
+ var bgColor = computedStyle.backgroundColor == "rgba(0, 0, 0, 0)" ?
"rgb(255, 255, 255)" : computedStyle.backgroundColor;
var defAttrs = {
"font-style": computedStyle.fontStyle,
"font-size": aFontSize,
"background-color": bgColor,
"font-weight": aFontWeight ? aFontWeight : kNormalFontWeight,
"color": computedStyle.color,
--- a/accessible/tests/mochitest/attributes/test_obj_css.html
+++ b/accessible/tests/mochitest/attributes/test_obj_css.html
@@ -23,17 +23,17 @@
this.accessible = getAccessible(aID);
this.eventSeq = [
new invokerChecker(EVENT_HIDE, this.accessible)
];
this.invoke = function removeElm_invoke()
{
- this.node.parentNode.removeChild(this.node);
+ this.node.remove();
}
this.check = function removeElm_check()
{
testAbsentCSSAttrs(this.accessible);
}
this.getID = function removeElm_getID()
--- a/accessible/tests/mochitest/attributes/test_obj_group.html
+++ b/accessible/tests/mochitest/attributes/test_obj_group.html
@@ -197,17 +197,17 @@
testGroupAttrs("t1_li2", 2, 3);
testGroupAttrs("t1_li3", 3, 3);
// Test that group position information updates after deleting node.
testGroupAttrs("tree4_ti1", 1, 2, 1);
testGroupAttrs("tree4_ti2", 2, 2, 1);
var tree4element = document.getElementById("tree4_ti1");
var tree4acc = getAccessible("tree4");
- tree4element.parentNode.removeChild(tree4element);
+ tree4element.remove();
waitForEvent(EVENT_REORDER, tree4acc, function() {
testGroupAttrs("tree4_ti2", 1, 1, 1);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html
+++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html
@@ -416,17 +416,17 @@
{ role: ROLE_TEXT_LEAF } // plain text
]
};
testElm("dfn_container", obj);
//////////////////////////////////////////////////////////////////////////
// HTML:dialog
- todo(isAccessible("dialog"), "dialog element is not accessible");
+ ok(isAccessible("dialog"), "dialog element is not accessible");
//////////////////////////////////////////////////////////////////////////
// HTML:div
obj = {
role: ROLE_SECTION,
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
children: [
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -107,17 +107,17 @@ function waitForEvent(aEventType, aTarge
/**
* Generate mouse move over image map what creates image map accessible (async).
* See waitForImageMap() function.
*/
function waveOverImageMap(aImageMapID)
{
var imageMapNode = getNode(aImageMapID);
synthesizeMouse(imageMapNode, 10, 10, { type: "mousemove" },
- imageMapNode.ownerDocument.defaultView);
+ imageMapNode.ownerGlobal);
}
/**
* Call the given function when the tree of the given image map is built.
*/
function waitForImageMap(aImageMapID, aTestFunc)
{
waveOverImageMap(aImageMapID);
@@ -1592,17 +1592,17 @@ function moveCaretToDOMPoint(aID, aDOMPo
this.focus = aFocusTargetID ? getAccessible(aFocusTargetID) : null;
this.focusNode = this.focus ? this.focus.DOMNode : null;
this.invoke = function moveCaretToDOMPoint_invoke()
{
if (this.focusNode)
this.focusNode.focus();
- var selection = this.DOMPointNode.ownerDocument.defaultView.getSelection();
+ var selection = this.DOMPointNode.ownerGlobal.getSelection();
var selRange = selection.getRangeAt(0);
selRange.setStart(this.DOMPointNode, aDOMPointOffset);
selRange.collapse(true);
selection.removeRange(selRange);
selection.addRange(selRange);
}
@@ -1758,23 +1758,37 @@ function nofocusChecker(aID)
this.__proto__ = new focusChecker(aID);
this.unexpected = true;
}
/**
* Text inserted/removed events checker.
* @param aFromUser [in, optional] kNotFromUserInput or kFromUserInput
*/
-function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted, aFromUser)
+function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted, aFromUser, aAsync)
{
this.target = getNode(aID);
this.type = aIsInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
this.startOffset = aStart;
this.endOffset = aEnd;
this.textOrFunc = aTextOrFunc;
+ this.async = aAsync;
+
+ this.match = function stextChangeChecker_match(aEvent)
+ {
+ if (!(aEvent instanceof nsIAccessibleTextChangeEvent) ||
+ aEvent.accessible !== getAccessible(this.target)) {
+ return false;
+ }
+
+ let tcEvent = aEvent.QueryInterface(nsIAccessibleTextChangeEvent);
+ let modifiedText = (typeof this.textOrFunc === "function") ?
+ this.textOrFunc() : this.textOrFunc;
+ return modifiedText === tcEvent.modifiedText;
+ };
this.check = function textChangeChecker_check(aEvent)
{
aEvent.QueryInterface(nsIAccessibleTextChangeEvent);
var modifiedText = (typeof this.textOrFunc == "function") ?
this.textOrFunc() : this.textOrFunc;
var modifiedTextLen =
--- a/accessible/tests/mochitest/events/a11y.ini
+++ b/accessible/tests/mochitest/events/a11y.ini
@@ -7,16 +7,18 @@ support-files =
!/accessible/tests/mochitest/letters.gif
[test_aria_alert.html]
[test_aria_menu.html]
[test_aria_objattr.html]
[test_aria_owns.html]
[test_aria_statechange.html]
[test_attrs.html]
+[test_bug1322593.html]
+[test_bug1322593-2.html]
[test_caretmove.html]
[test_caretmove.xul]
[test_coalescence.html]
[test_contextmenu.html]
[test_descrchange.html]
[test_docload.html]
[test_docload.xul]
skip-if = buildapp == 'mulet'
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_bug1322593-2.html
@@ -0,0 +1,83 @@
+<html>
+
+<head>
+ <title>Accessible mutation events testing</title>
+
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ function changeMultipleElements()
+ {
+ this.node1 = getNode("span1");
+ this.node2 = getNode("span2");
+
+ this.eventSeq = [
+ new textChangeChecker("container", 0, 5, "hello", false, undefined, true),
+ new textChangeChecker("container", 6, 11, "world", false, undefined, true),
+ new orderChecker(),
+ new textChangeChecker("container", 0, 1, "a", true, undefined, true),
+ new textChangeChecker("container", 7, 8, "b", true, undefined, true)
+ ];
+
+ this.invoke = function changeMultipleElements_invoke()
+ {
+ this.node1.textContent = "a";
+ this.node2.textContent = "b";
+ }
+
+ this.getID = function changeMultipleElements_invoke_getID()
+ {
+ return "Change the text content of multiple sibling divs";
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Do tests
+// gA11yEventDumpToConsole = true; // debugging
+
+ var gQueue = null;
+ function doTests()
+ {
+ gQueue = new eventQueue();
+
+ gQueue.push(new changeMultipleElements());
+
+ gQueue.invoke(); // Will call SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTests);
+ </script>
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322593"
+ title="missing text change events when multiple elements updated at once">
+ Mozilla Bug 1322593
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <div id="container">
+ <span id="span1">hello</span>
+ <span>your</span>
+ <span id="span2">world</span>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_bug1322593.html
@@ -0,0 +1,80 @@
+<html>
+
+<head>
+ <title>Accessible mutation events testing</title>
+
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ function changeMultipleElements()
+ {
+ this.node1 = getNode("div1");
+ this.node2 = getNode("div2");
+
+ this.eventSeq = [
+ new textChangeChecker("div1", 0, 5, "hello", false, undefined, true),
+ new textChangeChecker("div2", 0, 5, "world", false, undefined, true),
+ new orderChecker(),
+ new textChangeChecker("div1", 0, 1, "a", true, undefined, true),
+ new textChangeChecker("div2", 0, 1, "b", true, undefined, true)
+ ];
+
+ this.invoke = function changeMultipleElements_invoke()
+ {
+ this.node1.textContent = "a";
+ this.node2.textContent = "b";
+ }
+
+ this.getID = function changeMultipleElements_invoke_getID()
+ {
+ return "Change the text content of multiple sibling divs";
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Do tests
+// gA11yEventDumpToConsole = true; // debugging
+
+ var gQueue = null;
+ function doTests()
+ {
+ gQueue = new eventQueue();
+
+ gQueue.push(new changeMultipleElements());
+
+ gQueue.invoke(); // Will call SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTests);
+ </script>
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322593"
+ title="missing text change events when multiple elements updated at once">
+ Mozilla Bug 1322593
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <div id="div1">hello</div>
+ <div id="div2">world</div>
+</body>
+</html>
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -69,17 +69,17 @@
}
// Implementation details
this.invokeAction = function coalescenceBase_invokeAction(aNode, aAction)
{
switch (aAction) {
case kRemoveElm:
- aNode.parentNode.removeChild(aNode);
+ aNode.remove();
break;
case kHideElm:
aNode.style.display = "none";
break;
case kAddElm:
if (aNode == this.parentNode)
@@ -323,18 +323,18 @@
new invokerChecker(EVENT_REORDER, getNode(aParentId).parentNode),
new unexpectedInvokerChecker(EVENT_HIDE, getAccessible(aChild1Id)),
new unexpectedInvokerChecker(EVENT_HIDE, getAccessible(aChild2Id)),
new unexpectedInvokerChecker(EVENT_REORDER, getAccessible(aParentId))
];
this.invoke = function removeGrandChildrenNHideParent_invoke()
{
- this.child1.parentNode.removeChild(this.child1);
- this.child2.parentNode.removeChild(this.child2);
+ this.child1.remove();
+ this.child2.remove();
this.parent.hidden = true;
}
this.getID = function removeGrandChildrenNHideParent_getID() {
return "remove grand children of different parents and then hide their grand parent";
}
}
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul
+++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul
@@ -156,17 +156,17 @@
function focusOnMouseOver(aIDFunc, aIDFuncArg)
{
this.eventSeq = [ new focusChecker(aIDFunc, aIDFuncArg) ];
this.invoke = function focusOnMouseOver_invoke()
{
this.id = aIDFunc.call(null, aIDFuncArg);
this.node = getNode(this.id);
- this.window = this.node.ownerDocument.defaultView;
+ this.window = this.node.ownerGlobal;
if (this.node.localName == "tree") {
var tree = getAccessible(this.node);
var accessible = getAccessible(this.id);
if (tree != accessible) {
var itemX = {}, itemY = {}, treeX = {}, treeY = {};
accessible.getBounds(itemX, itemY, {}, {});
tree.getBounds(treeX, treeY, {}, {});
@@ -214,17 +214,17 @@
aFocusTargetFunc, aFocusTargetFuncArg)
{
this.eventSeq = [ new focusChecker(aFocusTargetFunc, aFocusTargetFuncArg) ];
this.invoke = function selectByClick_invoke()
{
var id = aIDFunc.call(null, aIDFuncArg);
var node = getNode(id);
- var targetWindow = node.ownerDocument.defaultView;
+ var targetWindow = node.ownerGlobal;
var x = 0, y = 0;
if (node.localName == "tree") {
var tree = getAccessible(node);
var accessible = getAccessible(id);
if (tree != accessible) {
var itemX = {}, itemY = {}, treeX = {}, treeY = {};
accessible.getBounds(itemX, itemY, {}, {});
--- a/accessible/tests/mochitest/events/test_focus_name.html
+++ b/accessible/tests/mochitest/events/test_focus_name.html
@@ -68,30 +68,30 @@
var gTooltipElm = null;
function doTests()
{
gButtonElm = getNode("button");
gTextboxElm = getNode("textbox");
gTooltipElm = getNode("tooltip");
- gButtonElm.addEventListener("focus", gFocusHandler, false);
- gButtonElm.addEventListener("blur", gBlurHandler, false);
- gTextboxElm.addEventListener("focus", gFocusHandler, false);
- gTextboxElm.addEventListener("blur", gBlurHandler, false);
+ gButtonElm.addEventListener("focus", gFocusHandler);
+ gButtonElm.addEventListener("blur", gBlurHandler);
+ gTextboxElm.addEventListener("focus", gFocusHandler);
+ gTextboxElm.addEventListener("blur", gBlurHandler);
// The aria-describedby is changed on DOM focus. Accessible description
// should be updated when a11y focus is fired.
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_FOCUS);
gQueue.onFinish = function()
{
- gButtonElm.removeEventListener("focus", gFocusHandler, false);
- gButtonElm.removeEventListener("blur", gBlurHandler, false);
- gTextboxElm.removeEventListener("focus", gFocusHandler, false);
- gTextboxElm.removeEventListener("blur", gBlurHandler, false);
+ gButtonElm.removeEventListener("focus", gFocusHandler);
+ gButtonElm.removeEventListener("blur", gBlurHandler);
+ gTextboxElm.removeEventListener("focus", gFocusHandler);
+ gTextboxElm.removeEventListener("blur", gBlurHandler);
}
var descr = "It's a tooltip";
gQueue.push(new synthFocus("button", new actionChecker("button", descr)));
gQueue.push(new synthTab("textbox", new actionChecker("textbox", descr)));
gQueue.invoke(); // Will call SimpleTest.finish();
}
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -197,17 +197,17 @@
var eventTypes = aEventTypes || kHideEvents;
var doNotExpectEvents = (aEventTypes == kNoEvents);
this.__proto__ = new mutateA11yTree(aNodeOrID, eventTypes,
doNotExpectEvents);
this.invoke = function removeFromDOM_invoke()
{
- this.DOMNode.parentNode.removeChild(this.DOMNode);
+ this.DOMNode.remove();
}
this.getID = function removeFromDOM_getID()
{
return prettyName(aNodeOrID) + " remove from DOM.";
}
if (aTargetsFunc && (eventTypes & kHideEvent))
@@ -382,22 +382,22 @@
this.txt = null;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, function() { return this.txt; }.bind(this))
];
this.invoke = function hideNDestroyDoc_invoke()
{
this.txt = getAccessible('c5').firstChild.firstChild;
- this.txt.DOMNode.parentNode.removeChild(this.txt.DOMNode);
+ this.txt.DOMNode.remove();
}
this.check = function hideNDestroyDoc_check()
{
- getNode('c5').parentNode.removeChild(getNode('c5'));
+ getNode('c5').remove();
}
this.getID = function hideNDestroyDoc_getID()
{
return "remove text node and destroy a document on hide event";
}
}
@@ -409,23 +409,23 @@
];
this.invoke = function hideHideNDestroyDoc_invoke()
{
var doc = getAccessible('c6').firstChild;
var l1 = doc.firstChild;
this.target = l1.firstChild;
var l2 = doc.lastChild;
- l1.DOMNode.removeChild(l1.DOMNode.firstChild);
- l2.DOMNode.removeChild(l2.DOMNode.firstChild);
+ l1.DOMNode.firstChild.remove();
+ l2.DOMNode.firstChild.remove();
}
this.check = function hideHideNDestroyDoc_check()
{
- getNode('c6').parentNode.removeChild(getNode('c6'));
+ getNode('c6').remove();
}
this.getID = function hideHideNDestroyDoc_getID()
{
return "remove text nodes (2 events in the queue) and destroy a document on first hide event";
}
}
--- a/accessible/tests/mochitest/events/test_text.html
+++ b/accessible/tests/mochitest/events/test_text.html
@@ -46,17 +46,17 @@
*/
function removeChildSpan(aID)
{
this.__proto__ = new textRemoveInvoker(aID, 0, 5, "33322");
this.invoke = function removeChildSpan_invoke()
{
// remove HTML span, a first child of the node
- this.DOMNode.removeChild(this.DOMNode.firstChild);
+ this.DOMNode.firstChild.remove();
}
this.getID = function removeChildSpan_getID()
{
return "Remove inaccessible span containing accessible nodes" + prettyName(aID);
}
}
@@ -157,17 +157,17 @@
this.invoke = function removeChildren_invoke()
{
if (aLastToFirst) {
while (this.DOMNode.firstChild)
this.DOMNode.removeChild(this.DOMNode.lastChild);
} else {
while (this.DOMNode.firstChild)
- this.DOMNode.removeChild(this.DOMNode.firstChild);
+ this.DOMNode.firstChild.remove();
}
}
this.getID = function removeChildren_getID()
{
return "remove children of " + prettyName(aID) +
(aLastToFirst ? " from last to first" : " from first to last");
}
--- a/accessible/tests/mochitest/grid.js
+++ b/accessible/tests/mochitest/grid.js
@@ -59,18 +59,18 @@ function grid(aTableIdentifier)
return cell;
}
}
return null;
}
this.initGrid = function initGrid()
{
- this.table.addEventListener("keypress", this, false);
- this.table.addEventListener("click", this, false);
+ this.table.addEventListener("keypress", this);
+ this.table.addEventListener("click", this);
}
this.handleEvent = function handleEvent(aEvent)
{
if (aEvent instanceof nsIDOMKeyEvent)
this.handleKeyEvent(aEvent);
else
this.handleClickEvent(aEvent);
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -144,18 +144,17 @@ var AccessFuTest = {
AccessFu.attach(getMainChromeWindow(window));
AccessFu.readyCallback = function readyCallback() {
// Enable logging to the console service.
Logger.test = true;
Logger.logLevel = Logger.DEBUG;
};
- var prefs = [['accessibility.accessfu.notify_output', 1],
- ['dom.mozSettings.enabled', true]];
+ var prefs = [['accessibility.accessfu.notify_output', 1]];
prefs.push.apply(prefs, aAdditionalPrefs);
this.originalDwellThreshold = GestureSettings.dwellThreshold;
this.originalSwipeMaxDuration = GestureSettings.swipeMaxDuration;
this.originalMaxGestureResolveTimeout =
GestureSettings.maxGestureResolveTimeout;
// https://bugzilla.mozilla.org/show_bug.cgi?id=1001945 - sometimes
// SimpleTest.executeSoon timeout is bigger than the timer settings in
--- a/accessible/tests/mochitest/jsat/output.js
+++ b/accessible/tests/mochitest/jsat/output.js
@@ -55,16 +55,17 @@ function testContextOutput(expected, aAc
function testObjectOutput(aAccOrElmOrID, aGenerator) {
var accessible = getAccessible(aAccOrElmOrID);
if (!accessible.name || !accessible.name.trim()) {
return;
}
var context = new PivotContext(accessible);
var output = aGenerator.genForObject(accessible, context);
var outputOrder;
+ // eslint-disable-next-line mozilla/use-default-preference-values
try {
outputOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);
} catch (ex) {
// PREF_UTTERANCE_ORDER not set.
outputOrder = 0;
}
var expectedNameIndex = outputOrder === 0 ? output.length - 1 : 0;
var nameIndex = output.indexOf(accessible.name);
--- a/accessible/tests/mochitest/jsat/test_content_text.html
+++ b/accessible/tests/mochitest/jsat/test_content_text.html
@@ -63,26 +63,26 @@
{ android_todo: true /* Bug 980512 */})],
// Editable text tests.
[ContentMessages.focusSelector('textarea'),
new ExpectedAnnouncement('editing'),
new ExpectedEditState({
editing: true,
multiline: true,
- atStart: false,
- atEnd: true
+ atStart: true,
+ atEnd: false
}),
new ExpectedCursorChange(
['Please refrain from Mayoneggs during this salmonella scare.',
{string: 'textarea'}]),
- new ExpectedTextSelectionChanged(59, 59)
+ new ExpectedTextSelectionChanged(0, 0)
],
[ContentMessages.activateCurrent(10),
- new ExpectedTextCaretChanged(10, 59),
+ new ExpectedTextCaretChanged(0, 10),
new ExpectedEditState({ editing: true,
multiline: true,
atStart: false,
atEnd: false }),
new ExpectedTextSelectionChanged(10, 10)],
[ContentMessages.activateCurrent(20),
new ExpectedTextCaretChanged(10, 20),
new ExpectedTextSelectionChanged(20, 20)
@@ -131,17 +131,16 @@
new ExpectedClickAction(),
new ExpectedAnnouncement('editing'),
new ExpectedEditState({
editing: true,
multiline: false,
atStart: true,
atEnd: true
}, { focused: 'input[type=text]' }),
- new ExpectedTextSelectionChanged(0, 0),
new ExpectedTextSelectionChanged(0, 0)
],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(
['So we don\'t get dessert?', {string: 'label'}]),
new ExpectedAnnouncement('navigating'),
new ExpectedEditState({
editing: false,
--- a/accessible/tests/mochitest/jsat/test_output.html
+++ b/accessible/tests/mochitest/jsat/test_output.html
@@ -120,24 +120,16 @@ https://bugzilla.mozilla.org/show_bug.cg
{"string": "listAbbr"}, {"string": "linkAbbr"}, "Apples",
{"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"},
"Peaches", {"string": "linkAbbr"}, "Plums"], ["Apples",
{"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"},
"Peaches", {"string": "linkAbbr"}, "Plums", {"string": "linkAbbr"},
{"string": "listAbbr"},
{"string": "cellInfoAbbr", "args": [ 1, 1]}]]
}, {
- accOrElmOrID: "date",
- expectedUtterance: [[{"string": "textInputType_date"},
- {"string": "entry"}, "2011-09-29"], ["2011-09-29",
- {"string": "textInputType_date"}, {"string": "entry"}]],
- expectedBraille: [[{"string": "textInputType_date"},
- {"string": "entryAbbr"}, "2011-09-29"], ["2011-09-29",
- {"string": "textInputType_date"}, {"string": "entryAbbr"}]]
- }, {
accOrElmOrID: "email",
expectedUtterance: [[{"string": "textInputType_email"},
{"string": "entry"}, "test@example.com"], ["test@example.com",
{"string": "textInputType_email"}, {"string": "entry"}]],
expectedBraille: [[{"string": "textInputType_email"},
{"string": "entryAbbr"}, "test@example.com"], ["test@example.com",
{"string": "textInputType_email"}, {"string": "entryAbbr"}]]
}, {
@@ -614,17 +606,16 @@ https://bugzilla.mozilla.org/show_bug.cg
<label id="label3">First name: <input id="input3" value="Joe"></label>
<label id="label4">Points:
<input id="input4" type="range" name="points" min="1" max="10" value="3">
</label>
<label for="input5">Boring label</label><input id="input5" type="checkbox" checked></input>
<label for="password">Secret Password</label><input id="password" type="password"></input>
<label for="radio_unselected">any old radio button</label><input id="radio_unselected" type="radio"></input>
<label for="radio_selected">a unique radio button</label><input id="radio_selected" type="radio" checked></input>
- <input id="date" type="date" value="2011-09-29" />
<input id="email" type="email" value="test@example.com" />
<input id="search" type="search" value="This is a search" />
<input id="tel" type="tel" value="555-5555" />
<input id="url" type="url" value="http://example.com" />
<input id="textInput" type="text" value="This is text." />
<label>Points: <input id="range" type="range" name="points" min="1" max="10" value="3"></label>
<div id="togglebutton_notpressed" aria-pressed="false" role="button" tabindex="-1">I am not pressed</div>
<div id="togglebutton_pressed" aria-pressed="true" role="button" tabindex="-1">I am pressed!</div>
--- a/accessible/tests/mochitest/layout.js
+++ b/accessible/tests/mochitest/layout.js
@@ -230,17 +230,17 @@ function getBoundsForDOMElm(aID)
else {
var rect = elm.getBoundingClientRect();
x = rect.left;
y = rect.top;
width = rect.width;
height = rect.height;
}
- var elmWindow = elm.ownerDocument.defaultView;
+ var elmWindow = elm.ownerGlobal;
return CSSToDevicePixels(elmWindow,
x + elmWindow.mozInnerScreenX,
y + elmWindow.mozInnerScreenY,
width,
height);
}
function CSSToDevicePixels(aWindow, aX, aY, aWidth, aHeight)
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -311,17 +311,17 @@ function testNameForSubtreeRule(aElm, aR
if (gDumpToConsole) {
dump("\nProcessed from subtree rule. Wait for reorder event on " +
prettyName(aElm) + "\n");
}
waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator);
while (aElm.firstChild)
- aElm.removeChild(aElm.firstChild);
+ aElm.firstChild.remove();
}
/**
* Return array of 'rule' elements. Used in conjunction with
* getRuleElmsFromRulesetElm() function.
*/
function getRuleElmsByRulesetId(aRulesetId)
{
--- a/accessible/tests/mochitest/pivot.js
+++ b/accessible/tests/mochitest/pivot.js
@@ -471,17 +471,17 @@ function removeVCPositionChecker(aDocAcc
* set to it.
*/
function removeVCPositionInvoker(aDocAcc, aPosNode)
{
this.accessible = getAccessible(aPosNode);
this.invoke = function removeVCPositionInvoker_invoke()
{
aDocAcc.virtualCursor.position = this.accessible;
- aPosNode.parentNode.removeChild(aPosNode);
+ aPosNode.remove();
};
this.getID = function removeVCPositionInvoker_getID()
{
return "Bring virtual cursor to accessible, and remove its DOM node.";
};
this.eventSeq = [
@@ -518,17 +518,17 @@ function removeVCRootChecker(aPivot)
* pivot. Should have more than one child.
*/
function removeVCRootInvoker(aRootNode)
{
this.pivot = gAccService.createAccessiblePivot(getAccessible(aRootNode));
this.invoke = function removeVCRootInvoker_invoke()
{
this.pivot.position = this.pivot.root.firstChild;
- aRootNode.parentNode.removeChild(aRootNode);
+ aRootNode.remove();
};
this.getID = function removeVCRootInvoker_getID()
{
return "Remove root of pivot from tree.";
};
this.eventSeq = [
--- a/accessible/tests/mochitest/states/a11y.ini
+++ b/accessible/tests/mochitest/states/a11y.ini
@@ -29,9 +29,9 @@ skip-if = os == 'mac' && os_version == '
[test_popup.xul]
[test_selects.html]
[test_stale.html]
[test_tabs.xul]
[test_textbox.xul]
[test_tree.xul]
[test_visibility.html]
[test_visibility.xul]
-skip-if = buildapp == "mulet"
+skip-if = asan # Bug 1199631
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -174,16 +174,19 @@
STATE_READONLY, 0);
testStates("aria_treegrid_readonly_rowheader_inherited", STATE_READONLY, 0,
0, EXT_STATE_EDITABLE);
testStates("aria_treegrid_readonly_cell_editable", 0, EXT_STATE_EDITABLE,
STATE_READONLY, 0);
testStates("aria_treegrid_readonly_cell_inherited", STATE_READONLY, 0,
0, EXT_STATE_EDITABLE);
+ // aria-readonly on directory
+ testStates("aria_directory", STATE_READONLY);
+
// aria-selectable
testStates("aria_selectable_listitem", STATE_SELECTABLE | STATE_SELECTED);
// active state caused by aria-activedescendant
testStates("as_item1", 0, EXT_STATE_ACTIVE);
testStates("as_item2", 0, 0, 0, EXT_STATE_ACTIVE);
// universal ARIA properties inherited from file input control
@@ -620,10 +623,13 @@
<div role="treeitem">G</div>
<div role="treeitem">g</div>
</div>
<div id="aria_treegrid_disabled" role="treegrid" aria-disabled="true">
<div role="row"><div role="gridcell">H</div></div>
<div role="row"><div role="gridcell">h</div></div>
</div>
+ <!-- Test that directory is readonly -->
+ <div id="aria_directory" role="directory"></div>
+
</body>
</html>
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -102,16 +102,17 @@
testStates(valid[i] + "2", 0, 0, STATE_INVALID);
}
////////////////////////////////////////////////////////////////////////////
// 'invalid' state
// (per spec, min/maxlength validity is affected by interactive edits)
var mininp = document.getElementById("minlength");
mininp.focus();
+ mininp.setSelectionRange(mininp.value.length, mininp.value.length);
synthesizeKey("VK_BACK_SPACE", {});
ok(!mininp.validity.valid,
"input should be invalid after interactive edits");
testStates(mininp, STATE_INVALID);
// inputs currently cannot be made longer than maxlength interactively,
// so we're not testing that case.
////////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/test_bug420863.html
+++ b/accessible/tests/mochitest/test_bug420863.html
@@ -41,17 +41,17 @@ https://bugzilla.mozilla.org/show_bug.cg
var td3Node = getNode("td3");
// register 'click' event handler
gClickHandler = {
handleEvent: function handleEvent(aEvent)
{
}
};
- td3Node.addEventListener("click", gClickHandler, false);
+ td3Node.addEventListener("click", gClickHandler);
// check actions
var actionsArray = [
{
ID: "td2", // "onclick" attribute
actionName: "click",
actionIndex: 0,
events: CLICK_EVENTS
@@ -59,17 +59,17 @@ https://bugzilla.mozilla.org/show_bug.cg
{
ID: td3Node,
actionName: "click",
actionIndex: 0,
events: CLICK_EVENTS,
checkOnClickEvent: function check(aEvent)
{
// unregister click event handler
- this.ID.removeEventListener("click", gClickHandler, false);
+ this.ID.removeEventListener("click", gClickHandler);
// check actions
is(getAccessible(this.ID).actionCount, 0,
"td3 shouldn't have actions");
}
}
];
--- a/accessible/tests/mochitest/textattrs/test_general.html
+++ b/accessible/tests/mochitest/textattrs/test_general.html
@@ -48,17 +48,17 @@
attrs = {};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
attrs = { "font-weight": kBoldFontWeight };
testTextAttrs(ID, 7, attrs, defAttrs, 7, 12);
var tempElem = getNode(ID).firstChild.nextSibling.firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"font-style": gComputedStyle.fontStyle,
"font-weight": kBoldFontWeight };
testTextAttrs(ID, 13, attrs, defAttrs, 12, 19);
attrs = { "font-weight": kBoldFontWeight };
testTextAttrs(ID, 20, attrs, defAttrs, 19, 23);
attrs = {};
@@ -66,66 +66,66 @@
//////////////////////////////////////////////////////////////////////////
// area3
ID = "area3";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
testDefaultTextAttrs(ID, defAttrs);
tempElem = getNode(ID).firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 6);
tempElem = tempElem.firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 6, attrs, defAttrs, 6, 26);
tempElem = tempElem.parentNode;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 26, attrs, defAttrs, 26, 27);
tempElem = tempElem.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color,
"background-color": gComputedStyle.backgroundColor};
testTextAttrs(ID, 27, attrs, defAttrs, 27, 50);
//////////////////////////////////////////////////////////////////////////
// area4
ID = "area4";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
testDefaultTextAttrs(ID, defAttrs);
tempElem = getNode(ID).firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 16);
tempElem = tempElem.nextSibling.firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 16, attrs, defAttrs, 16, 33);
tempElem = tempElem.parentNode;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 34, attrs, defAttrs, 33, 46);
//////////////////////////////////////////////////////////////////////////
// area5: "Green!*!RedNormal"
ID = "area5";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
testDefaultTextAttrs(ID, defAttrs);
// Green
tempElem = getNode(ID).firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
// br
attrs = {};
testTextAttrs(ID, 5, attrs, defAttrs, 5, 6);
// img, embedded accessible, no attributes
@@ -133,17 +133,17 @@
testTextAttrs(ID, 6, attrs, {}, 6, 7);
// br
attrs = {};
testTextAttrs(ID, 7, attrs, defAttrs, 7, 8);
// Red
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 9, attrs, defAttrs, 8, 11);
// Normal
attrs = {};
testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
//////////////////////////////////////////////////////////////////////////
@@ -210,45 +210,45 @@
attrs = {"language": "ru"};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 6);
attrs = {};
testTextAttrs(ID, 6, attrs, defAttrs, 6, 7);
tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "background-color": gComputedStyle.backgroundColor};
testTextAttrs(ID, 13, attrs, defAttrs, 7, 20);
attrs = {};
testTextAttrs(ID, 20, attrs, defAttrs, 20, 21);
attrs = {"language": "de"};
testTextAttrs(ID, 21, attrs, defAttrs, 21, 36);
attrs = {};
testTextAttrs(ID, 36, attrs, defAttrs, 36, 44);
attrs = {};
testTextAttrs(ID, 37, attrs, defAttrs, 36, 44);
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 44, attrs, defAttrs, 44, 51);
tempElem = tempElem.firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"font-weight": kBoldFontWeight,
"color": gComputedStyle.color};
testTextAttrs(ID, 51, attrs, defAttrs, 51, 55);
tempElem = tempElem.parentNode;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 55, attrs, defAttrs, 55, 62);
//////////////////////////////////////////////////////////////////////////
// area9, different single style spans in styled paragraph
ID = "area9";
defAttrs = buildDefaultTextAttrs(ID, "10pt");
testDefaultTextAttrs(ID, defAttrs);
@@ -259,35 +259,35 @@
attrs = { "font-size": "12pt" };
testTextAttrs(ID, 7, attrs, defAttrs, 6, 12);
attrs = {};
testTextAttrs(ID, 13, attrs, defAttrs, 12, 21);
// Walk to the span with the different background color
tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "background-color": gComputedStyle.backgroundColor };
testTextAttrs(ID, 22, attrs, defAttrs, 21, 36);
attrs = {};
testTextAttrs(ID, 37, attrs, defAttrs, 36, 44);
// Walk from the background color span to the one with font-style
tempElem = tempElem.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "font-style": gComputedStyle.fontStyle };
testTextAttrs(ID, 45, attrs, defAttrs, 44, 61);
attrs = {};
testTextAttrs(ID, 62, attrs, defAttrs, 61, 69);
// Walk from span with font-style to the one with font-family.
tempElem = tempElem.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "font-family": kMonospaceFontFamily };
testTextAttrs(ID, 70, attrs, defAttrs, 69, 83);
attrs = {};
testTextAttrs(ID, 84, attrs, defAttrs, 83, 91);
attrs = {
"text-underline-style": "solid",
@@ -337,35 +337,35 @@
attrs = { "font-size": "14pt" };
testTextAttrs(ID, 7, attrs, defAttrs, 7, 13);
attrs = {};
testTextAttrs(ID, 13, attrs, defAttrs, 13, 22);
// Walk to the span with the different background color
tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "background-color": gComputedStyle.backgroundColor };
testTextAttrs(ID, 23, attrs, defAttrs, 22, 37);
attrs = {};
testTextAttrs(ID, 38, attrs, defAttrs, 37, 45);
// Walk from the background color span to the one with font-style
tempElem = tempElem.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = {"font-style": gComputedStyle.fontStyle};
testTextAttrs(ID, 46, attrs, defAttrs, 45, 62);
attrs = {};
testTextAttrs(ID, 63, attrs, defAttrs, 62, 70);
// Walk from span with font-style to the one with font-family.
tempElem = tempElem.nextSibling.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "font-family": kMonospaceFontFamily };
testTextAttrs(ID, 71, attrs, defAttrs, 70, 84);
attrs = {};
testTextAttrs(ID, 85, attrs, defAttrs, 84, 92);
attrs = {
"text-underline-style": "solid",
@@ -550,17 +550,17 @@
// text enclosed in mark tag will have a different background color
ID = "area19";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
attrs = {};
testTextAttrs(ID, 0, attrs, defAttrs, 0, 10);
tempElem = getNode(ID).firstChild.nextSibling;
- gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
+ gComputedStyle = document.defaultView.getComputedStyle(tempElem);
attrs = { "background-color": gComputedStyle.backgroundColor };
testTextAttrs(ID, 11, attrs, defAttrs, 10, 17);
attrs = {};
testTextAttrs(ID, 18, attrs, defAttrs, 17, 28);
//////////////////////////////////////////////////////////////////////////
// area20, "aOffset as -1 (Mozilla Bug 789621)" test
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -218,17 +218,17 @@
new invokerChecker(EVENT_HIDE, getNode, "t1_checkbox"),
new invokerChecker(EVENT_SHOW, getNode, "t1_checkbox"),
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
];
this.invoke = function removeEl_invoke()
{
// remove a container of t1_subdiv
- getNode("t1_span").parentNode.removeChild(getNode("t1_span"));
+ getNode("t1_span").remove();
}
this.finalCheck = function removeEl_finalCheck()
{
// subdiv should go away
var tree =
{ SECTION: [
{ CHECKBUTTON: [ ] }, // explicit, t1_checkbox
@@ -518,25 +518,69 @@
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getAccessible(aParent))
];
this.invoke = function setARIAOwnsOnElToRemove_invoke()
{
getNode(aChild).setAttribute("aria-owns", "no_id");
getNode(aParent).removeChild(getNode(aChild));
- getNode(aParent).parentNode.removeChild(getNode(aParent));
+ getNode(aParent).remove();
}
this.getID = function setARIAOwnsOnElToRemove_getID()
{
return `set ARIA owns on an element, and then remove it, and then remove its parent`;
}
}
+ /**
+ * Set ARIA owns on inaccessible span element that contains
+ * accessible children. This will move children from the container for
+ * the span.
+ */
+ function test8()
+ {
+ this.eventSeq = [
+ new invokerChecker(EVENT_REORDER, "t8_container")
+ ];
+
+ this.invoke = function test8_invoke()
+ {
+ var tree =
+ { SECTION: [
+ { PUSHBUTTON: [] },
+ { ENTRY: [] },
+ { ENTRY: [] },
+ { ENTRY: [] }
+ ] };
+ testAccessibleTree("t8_container", tree);
+
+ getNode(t8_container).setAttribute("aria-owns", "t8_span t8_button");
+ }
+
+ this.finalCheck = function test8_finalCheck()
+ {
+ var tree =
+ { SECTION: [
+ { TEXT: [
+ { ENTRY: [] },
+ { ENTRY: [] },
+ { ENTRY: [] }
+ ] },
+ { PUSHBUTTON: [] }
+ ] };
+ testAccessibleTree("t8_container", tree);
+ }
+
+ this.getID = function test8_getID()
+ {
+ return `Set ARIA owns on inaccessible span element that contains accessible children`;
+ }
+ }
////////////////////////////////////////////////////////////////////////////
// Test
////////////////////////////////////////////////////////////////////////////
//gA11yEventDumpToConsole = true;
//enableLogging("tree,eventTree,verbose"); // debug stuff
@@ -575,16 +619,18 @@
"t5_container", "t5_radio t5_button t5_checkbox",
[ "t5_radio", "t5_button" ],
[ "RADIOBUTTON", "PUSHBUTTON", "CHECKBUTTON" ]));
gQueue.push(new removeNotARIAOwnedEl("t6_container", "t6_span"));
gQueue.push(new setARIAOwnsOnElToRemove("t7_parent", "t7_child"));
+ gQueue.push(new test8());
+
gQueue.invoke(); // SimpleTest.finish() will be called in the end
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
@@ -633,11 +679,15 @@
</div>
<div id="t6_fake" role="group"></div>
<div id="t7_container">
<div id="t7_parent">
<div id="t7_child"></div>
</div>
</div>
+
+ <div id="t8_container">
+ <input id="t8_button" type="button"><span id="t8_span"><input><input><input></span>
+ </div>
</body>
</html>
--- a/accessible/tests/mochitest/treeupdate/test_bug1175913.html
+++ b/accessible/tests/mochitest/treeupdate/test_bug1175913.html
@@ -42,28 +42,30 @@
{
return "Test that show event is sent when click listener is added";
}
}
function testRemoveListener()
{
this.eventSeq = [
- new invokerChecker(EVENT_HIDE, getNode("parent")),
+ new unexpectedInvokerChecker(EVENT_HIDE, getNode("parent")),
];
this.invoke = function testRemoveListener_invoke()
{
getNode("parent").removeEventListener("click", dummyListener);
}
this.finalCheck = function testRemoveListener_finalCheck()
{
- is(getAccessible("parent", null, null, DONOTFAIL_IF_NO_ACC), null, "Check that parent is not accessible.");
- is(getAccessible("child", null, null, DONOTFAIL_IF_NO_ACC), null, "Check that child is not accessible.");
+ ok(getAccessible("parent", null, null, DONOTFAIL_IF_NO_ACC),
+ "Parent stays accessible after click event listener is removed");
+ ok(!getAccessible("child", null, null, DONOTFAIL_IF_NO_ACC),
+ "Child stays inaccessible");
}
this.getID = function testRemoveListener_getID()
{
return "Test that hide event is sent when click listener is removed";
}
}
--- a/accessible/tests/mochitest/treeupdate/test_doc.html
+++ b/accessible/tests/mochitest/treeupdate/test_doc.html
@@ -261,17 +261,17 @@
this.__proto__ = new rootContentRemoved(aID);
this.invoke = function removeHTMLFromIFrameDoc_invoke()
{
this.preinvoke();
// Remove HTML element.
var docNode = getDocNode(aID);
- docNode.removeChild(docNode.firstChild);
+ docNode.firstChild.remove();
}
this.getID = function removeHTMLFromIFrameDoc_getID()
{
return "remove HTML element";
}
}
--- a/accessible/tests/mochitest/treeupdate/test_general.html
+++ b/accessible/tests/mochitest/treeupdate/test_general.html
@@ -59,17 +59,17 @@
function removeRemove(aContainer)
{
this.eventSeq = [
new invokerChecker(EVENT_REORDER, aContainer)
];
this.invoke = function removeRemove_invoke()
{
- getNode(aContainer).removeChild(getNode(aContainer).firstChild);
+ getNode(aContainer).firstChild.remove();
}
this.finalCheck = function removeRemove_finalCheck()
{
var accTree =
{ SECTION: [ // container
{ PUSHBUTTON: [ ] }
] };
--- a/accessible/tests/mochitest/treeupdate/test_imagemap.html
+++ b/accessible/tests/mochitest/treeupdate/test_imagemap.html
@@ -268,17 +268,17 @@
new invokerChecker(EVENT_HIDE, getImageMap, this),
new invokerChecker(EVENT_SHOW, this.imgNode),
new invokerChecker(EVENT_REORDER, this.container)
];
this.invoke = function removeMap_invoke()
{
this.imageMap = getAccessible(aImageMapID);
- this.mapNode.parentNode.removeChild(this.mapNode);
+ this.mapNode.remove();
}
this.finalCheck = function removeMap_finalCheck()
{
var accTree =
{ SECTION: [
{ GRAPHIC: [ ] }
] };
--- a/accessible/tests/mochitest/treeupdate/test_optgroup.html
+++ b/accessible/tests/mochitest/treeupdate/test_optgroup.html
@@ -72,17 +72,17 @@
{
this.selectNode = getNode(aID);
this.select = getAccessible(this.selectNode);
this.selectList = this.select.firstChild;
this.invoke = function removeOptGroup_invoke()
{
this.option1Node = this.selectNode.firstChild.firstChild;
- this.selectNode.removeChild(this.selectNode.firstChild);
+ this.selectNode.firstChild.remove();
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.selectList)
];
this.finalCheck = function removeOptGroup_finalCheck()
{
--- a/accessible/tests/mochitest/treeupdate/test_select.html
+++ b/accessible/tests/mochitest/treeupdate/test_select.html
@@ -1,12 +1,12 @@
<!DOCTYPE html>
<html>
<head>
- <title>Add select options test</title>
+ <title>HTML select options test</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
@@ -86,45 +86,65 @@
}
this.getID = function removeptions_getID()
{
return "test elements removal from a select";
}
}
- //gA11yEventDumpID = "debug";
+ /**
+ * Setting @href on option makes the accessible to recreate.
+ */
+ function setHrefOnOption()
+ {
+ this.eventSeq = [
+ new invokerChecker(EVENT_HIDE, 's2_o'),
+ new invokerChecker(EVENT_SHOW, 's2_o'),
+ ];
+
+ this.invoke = function setHrefOnOption_setHref()
+ {
+ getNode('s2_o').setAttribute('href', '1');
+ }
+
+ this.finalCheck = function() {
+ var tree =
+ { COMBOBOX: [
+ { COMBOBOX_LIST: [
+ { COMBOBOX_OPTION: [ ] }
+ ] }
+ ] };
+ testAccessibleTree('s2', tree);
+ }
+
+ this.getID = function removeptions_getID()
+ {
+ return "setting @href on select option";
+ }
+ }
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new addOptions("select"));
gQueue.push(new removeOptions("select"));
+ gQueue.push(new setHrefOnOption());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
-
- <a target="_blank"
- href="https://bugzilla.mozilla.org/show_bug.cgi?id=616452"
- title="Bug 616452 - Dynamically inserted select options aren't reflected in accessible tree">
- Mozilla Bug 616452</a>
- <a target="_blank"
- href="https://bugzilla.mozilla.org/show_bug.cgi?id=616940"
- title="Removed select option accessibles aren't removed until hide event is fired">
- Mozilla Bug 616940</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<select id="select"></select>
-
- <div id="debug"/>
+ <select id="s2"><option id="s2_o"></option></select>
</body>
</html>
--- a/accessible/tests/mochitest/treeupdate/test_shutdown.xul
+++ b/accessible/tests/mochitest/treeupdate/test_shutdown.xul
@@ -50,17 +50,17 @@
this.eventSeq = [
new invokerChecker(EVENT_REORDER, document)
];
this.invoke = function invoke()
{
this.lastItem = getAccessible(aID).lastChild;
this.lastCell = this.lastItem.lastChild;
- getNode(aID).parentNode.removeChild(getNode(aID));
+ getNode(aID).remove();
};
this.check = function check(aEvent)
{
testIsDefunct(this.tree, aID);
testIsDefunct(this.lastItem, "last item of " + aID);
if (this.lastCell) {
testIsDefunct(this.lastCell, "last item cell of " + aID);
--- a/accessible/tests/mochitest/treeupdate/test_textleaf.html
+++ b/accessible/tests/mochitest/treeupdate/test_textleaf.html
@@ -38,32 +38,26 @@
}
}
function setOnClickAttr(aID)
{
var node = getNode(aID);
node.setAttribute("onclick", "alert(3);");
var textLeaf = getAccessible(node).firstChild;
- is(textLeaf.actionCount, 1, "Wrong action numbers!");
+ is(textLeaf.actionCount, 1, "setOnClickAttr: wrong action numbers!");
}
function removeOnClickAttr(aID)
{
- this.__proto__ = new textLeafUpdate(aID, false);
-
- this.invoke = function removeOnClickAttr_invoke()
- {
- this.node.removeAttribute("onclick");
- }
-
- this.getID = function removeOnClickAttr_getID()
- {
- return "unmake " + prettyName(aID) + " linkable";
- }
+ var node = getNode(aID);
+ node.removeAttribute("onclick");
+ var textLeaf = getAccessible(node).firstChild;
+ is(textLeaf.actionCount, 0,
+ "removeOnClickAttr: wrong action numbers!");
}
function setOnClickNRoleAttrs(aID)
{
this.__proto__ = new textLeafUpdate(aID, true);
this.invoke = function setOnClickAttr_invoke()
{
@@ -124,20 +118,21 @@
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
// adds onclick on element, text leaf should inherit its action
setOnClickAttr("div");
+ // remove onclick attribute, text leaf shouldn't have any action
+ removeOnClickAttr("div");
+
// Call rest of event tests.
gQueue = new eventQueue();
- // remove onclick attribute, text leaf shouldn't have any action
- gQueue.push(new removeOnClickAttr("div"));
// set onclick attribute making span accessible, it's inserted into tree
// and adopts text leaf accessible, text leaf should have an action
gQueue.push(new setOnClickNRoleAttrs("span"));
// text data removal of text node should remove its text accessible
gQueue.push(new removeTextData("p", ROLE_PARAGRAPH));
gQueue.push(new removeTextData("pre", ROLE_TEXT_CONTAINER));
--- a/accessible/windows/ProxyWrappers.h
+++ b/accessible/windows/ProxyWrappers.h
@@ -11,17 +11,17 @@
#include "HyperTextAccessible.h"
namespace mozilla {
namespace a11y {
class ProxyAccessibleWrap : public AccessibleWrap
{
public:
- ProxyAccessibleWrap(ProxyAccessible* aProxy) :
+ explicit ProxyAccessibleWrap(ProxyAccessible* aProxy) :
AccessibleWrap(nullptr, nullptr)
{
mType = eProxyType;
mBits.proxy = aProxy;
}
virtual void Shutdown() override
{
@@ -33,17 +33,17 @@ public:
{
mBits.proxy->GetCOMInterface(aOutAccessible);
}
};
class HyperTextProxyAccessibleWrap : public HyperTextAccessibleWrap
{
public:
- HyperTextProxyAccessibleWrap(ProxyAccessible* aProxy) :
+ explicit HyperTextProxyAccessibleWrap(ProxyAccessible* aProxy) :
HyperTextAccessibleWrap(nullptr, nullptr)
{
mType = eProxyType;
mBits.proxy = aProxy;
}
virtual void Shutdown() override
{
@@ -55,17 +55,17 @@ public:
{
mBits.proxy->GetCOMInterface(aOutAccessible);
}
};
class DocProxyAccessibleWrap : public HyperTextProxyAccessibleWrap
{
public:
- DocProxyAccessibleWrap(ProxyAccessible* aProxy) :
+ explicit DocProxyAccessibleWrap(ProxyAccessible* aProxy) :
HyperTextProxyAccessibleWrap(aProxy)
{ mGenericTypes |= eDocument; }
void AddID(uint32_t aID, AccessibleWrap* aAcc)
{ mIDToAccessibleMap.Put(aID, aAcc); }
void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
AccessibleWrap* GetAccessibleByID(uint32_t aID) const
{ return mIDToAccessibleMap.Get(aID); }
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -58,18 +58,16 @@ ia2Accessible::QueryInterface(REFIID iid
}
////////////////////////////////////////////////////////////////////////////////
// IAccessible2
STDMETHODIMP
ia2Accessible::get_nRelations(long* aNRelations)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNRelations)
return E_INVALIDARG;
*aNRelations = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -79,26 +77,22 @@ ia2Accessible::get_nRelations(long* aNRe
if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
continue;
Relation rel = acc->RelationByType(sRelationTypePairs[idx].first);
if (rel.Next())
(*aNRelations)++;
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_relation(long aRelationIndex,
IAccessibleRelation** aRelation)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRelation || aRelationIndex < 0)
return E_INVALIDARG;
*aRelation = nullptr;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -119,27 +113,23 @@ ia2Accessible::get_relation(long aRelati
return S_OK;
}
relIdx++;
}
}
return E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_relations(long aMaxRelations,
IAccessibleRelation** aRelation,
long *aNRelations)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRelation || !aNRelations || aMaxRelations <= 0)
return E_INVALIDARG;
*aNRelations = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -155,25 +145,21 @@ ia2Accessible::get_relations(long aMaxRe
RefPtr<ia2AccessibleRelation> ia2Rel =
new ia2AccessibleRelation(relationType, &rel);
if (ia2Rel->HasTargets()) {
ia2Rel.forget(aRelation + (*aNRelations));
(*aNRelations)++;
}
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::role(long* aRole)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRole)
return E_INVALIDARG;
*aRole = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -199,67 +185,55 @@ ia2Accessible::role(long* aRole)
MOZ_ASSERT(!acc->IsProxy());
if (geckoRole == roles::ROW) {
Accessible* xpParent = acc->Parent();
if (xpParent && xpParent->Role() == roles::TREE_TABLE)
*aRole = ROLE_SYSTEM_OUTLINEITEM;
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::scrollTo(enum IA2ScrollType aScrollType)
{
- A11Y_TRYBLOCK_BEGIN
-
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
MOZ_ASSERT(!acc->IsProxy());
nsCoreUtils::ScrollTo(acc->Document()->PresShell(), acc->GetContent(),
aScrollType);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::scrollToPoint(enum IA2CoordinateType aCoordType,
long aX, long aY)
{
- A11Y_TRYBLOCK_BEGIN
-
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
MOZ_ASSERT(!acc->IsProxy());
acc->ScrollToPoint(geckoCoordType, aX, aY);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_groupPosition(long* aGroupLevel,
long* aSimilarItemsInGroup,
long* aPositionInGroup)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aGroupLevel || !aSimilarItemsInGroup || !aPositionInGroup)
return E_INVALIDARG;
*aGroupLevel = 0;
*aSimilarItemsInGroup = 0;
*aPositionInGroup = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
@@ -274,25 +248,21 @@ ia2Accessible::get_groupPosition(long* a
if (!groupPos.setSize && !groupPos.posInSet)
return S_FALSE;
*aGroupLevel = groupPos.level;
*aSimilarItemsInGroup = groupPos.setSize;
*aPositionInGroup = groupPos.posInSet;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_states(AccessibleStates* aStates)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStates)
return E_INVALIDARG;
*aStates = 0;
// XXX: bug 344674 should come with better approach that we have here.
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct()) {
@@ -342,159 +312,123 @@ ia2Accessible::get_states(AccessibleStat
if (state & states::VERTICAL)
*aStates |= IA2_STATE_VERTICAL;
if (state & states::CHECKED)
*aStates |= IA2_STATE_CHECKABLE;
if (state & states::PINNED)
*aStates |= IA2_STATE_PINNED;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_extendedRole(BSTR* aExtendedRole)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aExtendedRole)
return E_INVALIDARG;
*aExtendedRole = nullptr;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_localizedExtendedRole(BSTR* aLocalizedExtendedRole)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aLocalizedExtendedRole)
return E_INVALIDARG;
*aLocalizedExtendedRole = nullptr;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_nExtendedStates(long* aNExtendedStates)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNExtendedStates)
return E_INVALIDARG;
*aNExtendedStates = 0;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_extendedStates(long aMaxExtendedStates,
BSTR** aExtendedStates,
long* aNExtendedStates)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aExtendedStates || !aNExtendedStates)
return E_INVALIDARG;
*aExtendedStates = nullptr;
*aNExtendedStates = 0;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
BSTR** aLocalizedExtendedStates,
long* aNLocalizedExtendedStates)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aLocalizedExtendedStates || !aNLocalizedExtendedStates)
return E_INVALIDARG;
*aLocalizedExtendedStates = nullptr;
*aNLocalizedExtendedStates = 0;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_uniqueID(long* aUniqueID)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aUniqueID)
return E_INVALIDARG;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
*aUniqueID = AccessibleWrap::GetChildIDFor(acc);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_windowHandle(HWND* aWindowHandle)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aWindowHandle)
return E_INVALIDARG;
*aWindowHandle = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
*aWindowHandle = AccessibleWrap::GetHWNDFor(acc);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_indexInParent(long* aIndexInParent)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIndexInParent)
return E_INVALIDARG;
*aIndexInParent = -1;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
MOZ_ASSERT(!acc->IsProxy());
*aIndexInParent = acc->IndexInParent();
if (*aIndexInParent == -1)
return S_FALSE;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_locale(IA2Locale* aLocale)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aLocale)
return E_INVALIDARG;
// Language codes consist of a primary code and a possibly empty series of
// subcodes: language-code = primary-code ( "-" subcode )*
// Two-letter primary codes are reserved for [ISO639] language abbreviations.
// Any two-letter subcode is understood to be a [ISO3166] country code.
@@ -527,25 +461,21 @@ ia2Accessible::get_locale(IA2Locale* aLo
aLocale->country = ::SysAllocStringLen(lang.get() + 3, 2);
}
}
// Expose as a string if primary code or subcode cannot point to language or
// country abbreviations or if there are more than one subcode.
aLocale->variant = ::SysAllocString(lang.get());
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_attributes(BSTR* aAttributes)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAttributes)
return E_INVALIDARG;
*aAttributes = nullptr;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -553,42 +483,34 @@ ia2Accessible::get_attributes(BSTR* aAtt
// characters ":;=,\".
if (!acc->IsProxy()) {
nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
return ConvertToIA2Attributes(attributes, aAttributes);
}
MOZ_ASSERT(!acc->IsProxy());
return E_UNEXPECTED;
-
- A11Y_TRYBLOCK_END
}
////////////////////////////////////////////////////////////////////////////////
// IAccessible2_2
STDMETHODIMP
ia2Accessible::get_attribute(BSTR name, VARIANT* aAttribute)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAttribute)
return E_INVALIDARG;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
long* aCaretOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAccessible || !aCaretOffset)
return E_INVALIDARG;
*aAccessible = nullptr;
*aCaretOffset = -1;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
@@ -606,28 +528,24 @@ ia2Accessible::get_accessibleWithCaret(I
if (child != acc)
return S_FALSE;
*aAccessible = static_cast<IAccessible2*>(
static_cast<AccessibleWrap*>(accWithCaret));
(*aAccessible)->AddRef();
*aCaretOffset = caretOffset;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_relationTargetsOfType(BSTR aType,
long aMaxTargets,
IUnknown*** aTargets,
long* aNTargets)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aTargets || !aNTargets || aMaxTargets < 0)
return E_INVALIDARG;
*aNTargets = 0;
Maybe<RelationType> relationType;
for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
if (wcscmp(aType, sRelationTypePairs[idx].second) == 0) {
relationType.emplace(sRelationTypePairs[idx].first);
@@ -658,26 +576,22 @@ ia2Accessible::get_relationTargetsOfType
for (int32_t i = 0; i < *aNTargets; i++) {
AccessibleWrap* target= static_cast<AccessibleWrap*>(targets[i]);
(*aTargets)[i] = static_cast<IAccessible2*>(target);
(*aTargets)[i]->AddRef();
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2Accessible::get_selectionRanges(IA2Range** aRanges,
long *aNRanges)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRanges || !aNRanges)
return E_INVALIDARG;
*aNRanges = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -709,18 +623,16 @@ ia2Accessible::get_selectionRanges(IA2Ra
static_cast<AccessibleWrap*>(ranges[idx].EndContainer());
(*aRanges)[idx].active = static_cast<IAccessible2*>(active);
active->AddRef();
(*aRanges)[idx].activeOffset = ranges[idx].EndOffset();
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
////////////////////////////////////////////////////////////////////////////////
// Helpers
template<typename String>
static inline void
--- a/accessible/windows/ia2/ia2AccessibleAction.cpp
+++ b/accessible/windows/ia2/ia2AccessibleAction.cpp
@@ -34,53 +34,43 @@ ia2AccessibleAction::QueryInterface(REFI
return E_NOINTERFACE;
}
// IAccessibleAction
STDMETHODIMP
ia2AccessibleAction::nActions(long* aActionCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aActionCount)
return E_INVALIDARG;
*aActionCount = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
*aActionCount = acc->ActionCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleAction::doAction(long aActionIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
uint8_t index = static_cast<uint8_t>(aActionIndex);
return acc->DoAction(index) ? S_OK : E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aDescription)
return E_INVALIDARG;
*aDescription = nullptr;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -88,27 +78,23 @@ ia2AccessibleAction::get_description(lon
uint8_t index = static_cast<uint8_t>(aActionIndex);
acc->ActionDescriptionAt(index, description);
if (description.IsEmpty())
return S_FALSE;
*aDescription = ::SysAllocStringLen(description.get(),
description.Length());
return *aDescription ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
BSTR **aKeyBinding,
long *aNumBinding)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aKeyBinding)
return E_INVALIDARG;
*aKeyBinding = nullptr;
if (!aNumBinding)
return E_INVALIDARG;
*aNumBinding = 0;
@@ -138,25 +124,21 @@ ia2AccessibleAction::get_keyBinding(long
*(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
if (!*(aKeyBinding[0])) {
::CoTaskMemFree(*aKeyBinding);
return E_OUTOFMEMORY;
}
*aNumBinding = 1;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aName)
return E_INVALIDARG;
*aName = nullptr;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -164,25 +146,19 @@ ia2AccessibleAction::get_name(long aActi
nsAutoString name;
uint8_t index = static_cast<uint8_t>(aActionIndex);
acc->ActionNameAt(index, name);
if (name.IsEmpty())
return E_INVALIDARG;
*aName = ::SysAllocStringLen(name.get(), name.Length());
return *aName ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aLocalizedName)
return E_INVALIDARG;
*aLocalizedName = nullptr;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/windows/ia2/ia2AccessibleComponent.cpp
@@ -36,18 +36,16 @@ ia2AccessibleComponent::QueryInterface(R
return E_NOINTERFACE;
}
// IAccessibleComponent
STDMETHODIMP
ia2AccessibleComponent::get_locationInParent(long* aX, long* aY)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aX || !aY)
return E_INVALIDARG;
*aX = 0;
*aY = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
@@ -70,58 +68,49 @@ ia2AccessibleComponent::get_locationInPa
}
// The coordinates of the bounding box are given relative to the parent's
// coordinate system.
nsIntRect parentRect = acc->Parent()->Bounds();
*aX = rect.x - parentRect.x;
*aY = rect.y - parentRect.y;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleComponent::get_foreground(IA2Color* aForeground)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aForeground)
return E_INVALIDARG;
*aForeground = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
nsIFrame* frame = acc->GetFrame();
if (frame)
*aForeground = frame->StyleColor()->mColor;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleComponent::get_background(IA2Color* aBackground)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aBackground)
return E_INVALIDARG;
*aBackground = 0;
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
nsIFrame* frame = acc->GetFrame();
- if (frame)
- *aBackground = frame->StyleBackground()->mBackgroundColor;
+ if (frame) {
+ *aBackground = frame->StyleBackground()->BackgroundColor(frame);
+ }
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleEditableText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
@@ -17,137 +17,113 @@
using namespace mozilla::a11y;
// IAccessibleEditableText
STDMETHODIMP
ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
return E_INVALIDARG;
textAcc->CopyText(aStartOffset, aEndOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
return E_INVALIDARG;
textAcc->DeleteText(aStartOffset, aEndOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
{
- A11Y_TRYBLOCK_BEGIN
-
uint32_t length = ::SysStringLen(*aText);
nsAutoString text(*aText, length);
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidOffset(aOffset))
return E_INVALIDARG;
textAcc->InsertText(text, aOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
return E_INVALIDARG;
textAcc->CutText(aStartOffset, aEndOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::pasteText(long aOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidOffset(aOffset))
return E_INVALIDARG;
textAcc->PasteText(aOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
BSTR *aText)
{
- A11Y_TRYBLOCK_BEGIN
-
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
return E_INVALIDARG;
textAcc->DeleteText(aStartOffset, aEndOffset);
uint32_t length = ::SysStringLen(*aText);
nsAutoString text(*aText, length);
textAcc->InsertText(text, aStartOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
BSTR *aAttributes)
{
return E_NOTIMPL;
}
--- a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -40,18 +40,16 @@ ia2AccessibleHyperlink::QueryInterface(R
return ia2AccessibleAction::QueryInterface(iid, ppv);
}
// IAccessibleHyperlink
STDMETHODIMP
ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAnchor)
return E_INVALIDARG;
VariantInit(aAnchor);
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
MOZ_ASSERT(!thisObj->IsProxy());
@@ -72,25 +70,21 @@ ia2AccessibleHyperlink::get_anchor(long
void* instancePtr = nullptr;
HRESULT result = anchor->QueryInterface(IID_IUnknown, &instancePtr);
if (FAILED(result))
return result;
aAnchor->punkVal = static_cast<IUnknown*>(instancePtr);
aAnchor->vt = VT_UNKNOWN;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAnchorTarget) {
return E_INVALIDARG;
}
VariantInit(aAnchorTarget);
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
nsAutoCString uriStr;
@@ -119,87 +113,73 @@ ia2AccessibleHyperlink::get_anchorTarget
nsAutoString stringURI;
AppendUTF8toUTF16(uriStr, stringURI);
aAnchorTarget->vt = VT_BSTR;
aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
stringURI.Length());
return aAnchorTarget->bstrVal ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHyperlink::get_startIndex(long* aIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIndex)
return E_INVALIDARG;
*aIndex = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
if (thisObj->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!thisObj->IsLink())
return S_FALSE;
*aIndex = thisObj->StartOffset();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHyperlink::get_endIndex(long* aIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIndex)
return E_INVALIDARG;
*aIndex = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
if (thisObj->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!thisObj->IsLink())
return S_FALSE;
*aIndex = thisObj->EndOffset();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHyperlink::get_valid(boolean* aValid)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aValid)
return E_INVALIDARG;
*aValid = false;
MOZ_ASSERT(!HyperTextProxyFor(this));
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
if (thisObj->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!thisObj->IsLink())
return S_FALSE;
*aValid = thisObj->IsLinkValid();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
@@ -14,41 +14,35 @@
using namespace mozilla::a11y;
// IAccessibleHypertext
STDMETHODIMP
ia2AccessibleHypertext::get_nHyperlinks(long* aHyperlinkCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aHyperlinkCount)
return E_INVALIDARG;
*aHyperlinkCount = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
if (hyperText->IsDefunct())
return CO_E_OBJNOTCONNECTED;
*aHyperlinkCount = hyperText->LinkCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
IAccessibleHyperlink** aHyperlink)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aHyperlink)
return E_INVALIDARG;
*aHyperlink = nullptr;
AccessibleWrap* hyperLink;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
@@ -60,34 +54,28 @@ ia2AccessibleHypertext::get_hyperlink(lo
if (!hyperLink)
return E_FAIL;
*aHyperlink =
static_cast<IAccessibleHyperlink*>(hyperLink);
(*aHyperlink)->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aHyperlinkIndex)
return E_INVALIDARG;
*aHyperlinkIndex = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessibleWrap* hyperAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (hyperAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
*aHyperlinkIndex = hyperAcc->LinkIndexAtOffset(aCharIndex);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleImage.cpp
+++ b/accessible/windows/ia2/ia2AccessibleImage.cpp
@@ -38,45 +38,39 @@ ia2AccessibleImage::QueryInterface(REFII
return E_NOINTERFACE;
}
// IAccessibleImage
STDMETHODIMP
ia2AccessibleImage::get_description(BSTR* aDescription)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aDescription)
return E_INVALIDARG;
*aDescription = nullptr;
ImageAccessibleWrap* acc = static_cast<ImageAccessibleWrap*>(this);
if (acc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
nsAutoString description;
acc->Name(description);
if (description.IsEmpty())
return S_FALSE;
*aDescription = ::SysAllocStringLen(description.get(), description.Length());
return *aDescription ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
long* aX,
long* aY)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aX || !aY)
return E_INVALIDARG;
*aX = 0;
*aY = 0;
ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
if (imageAcc->IsDefunct())
@@ -85,35 +79,29 @@ ia2AccessibleImage::get_imagePosition(en
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
nsIntPoint pos = imageAcc->Position(geckoCoordType);
*aX = pos.x;
*aY = pos.y;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleImage::get_imageSize(long* aHeight, long* aWidth)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aHeight || !aWidth)
return E_INVALIDARG;
*aHeight = 0;
*aWidth = 0;
ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
if (imageAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
nsIntSize size = imageAcc->Size();
*aHeight = size.width;
*aWidth = size.height;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleRelation.cpp
+++ b/accessible/windows/ia2/ia2AccessibleRelation.cpp
@@ -29,97 +29,77 @@ IMPL_IUNKNOWN_QUERY_HEAD(ia2AccessibleRe
IMPL_IUNKNOWN_QUERY_IFACE(IUnknown)
IMPL_IUNKNOWN_QUERY_TAIL
// IAccessibleRelation
STDMETHODIMP
ia2AccessibleRelation::get_relationType(BSTR* aRelationType)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRelationType)
return E_INVALIDARG;
*aRelationType = nullptr;
#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
case RelationType::geckoType: \
*aRelationType = ::SysAllocString(ia2Type); \
break;
switch (mType) {
#include "RelationTypeMap.h"
}
return *aRelationType ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleRelation::get_localizedRelationType(BSTR *aLocalizedRelationType)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aLocalizedRelationType)
return E_INVALIDARG;
*aLocalizedRelationType = nullptr;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleRelation::get_nTargets(long *aNTargets)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNTargets)
return E_INVALIDARG;
*aNTargets = mTargets.Length();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
{
- A11Y_TRYBLOCK_BEGIN
-
if (aTargetIndex < 0 || (uint32_t)aTargetIndex >= mTargets.Length() || !aTarget)
return E_INVALIDARG;
AccessibleWrap* target =
static_cast<AccessibleWrap*>(mTargets[aTargetIndex].get());
*aTarget = static_cast<IAccessible*>(target);
(*aTarget)->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
long *aNTargets)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNTargets || !aTargets)
return E_INVALIDARG;
*aNTargets = 0;
long maxTargets = mTargets.Length();
if (maxTargets > aMaxTargets)
maxTargets = aMaxTargets;
for (long idx = 0; idx < maxTargets; idx++)
get_target(idx, aTargets + idx);
*aNTargets = maxTargets;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleTable.cpp
+++ b/accessible/windows/ia2/ia2AccessibleTable.cpp
@@ -55,64 +55,54 @@ ia2AccessibleTable::get_accessibleAt(lon
IUnknown** aAccessible)
{
return get_cellAt(aRowIdx, aColIdx, aAccessible);
}
STDMETHODIMP
ia2AccessibleTable::get_caption(IUnknown** aAccessible)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAccessible)
return E_INVALIDARG;
*aAccessible = nullptr;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
AccessibleWrap* caption = static_cast<AccessibleWrap*>(mTable->Caption());
if (!caption)
return S_FALSE;
(*aAccessible = static_cast<IAccessible*>(caption))->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
long* aChildIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aChildIdx)
return E_INVALIDARG;
*aChildIdx = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || aColIdx < 0 ||
static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
*aChildIdx = mTable->CellIndexAt(aRowIdx, aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aDescription)
return E_INVALIDARG;
*aDescription = nullptr;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
@@ -120,166 +110,134 @@ ia2AccessibleTable::get_columnDescriptio
nsAutoString descr;
mTable->ColDescription(aColIdx, descr);
if (descr.IsEmpty())
return S_FALSE;
*aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
return *aDescription ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
long* aSpan)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aSpan)
return E_INVALIDARG;
*aSpan = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || aColIdx < 0 ||
static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
*aSpan = mTable->ColExtentAt(aRowIdx, aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
long* aStartingRowIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAccessibleTable || !aStartingRowIndex)
return E_INVALIDARG;
*aAccessibleTable = nullptr;
*aStartingRowIndex = -1;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aColIdx)
return E_INVALIDARG;
*aColIdx = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aCellIdx < 0 ||
static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
return E_INVALIDARG;
*aColIdx = mTable->ColIndexAt(aCellIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_nColumns(long* aColCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aColCount)
return E_INVALIDARG;
*aColCount = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
*aColCount = mTable->ColCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_nRows(long* aRowCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowCount)
return E_INVALIDARG;
*aRowCount = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
*aRowCount = mTable->RowCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_nSelectedChildren(long* aChildCount)
{
return get_nSelectedCells(aChildCount);
}
STDMETHODIMP
ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aColCount)
return E_INVALIDARG;
*aColCount = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
*aColCount = mTable->SelectedColCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowCount)
return E_INVALIDARG;
*aRowCount = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
*aRowCount = mTable->SelectedRowCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aDescription)
return E_INVALIDARG;
*aDescription = nullptr;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
@@ -287,87 +245,71 @@ ia2AccessibleTable::get_rowDescription(l
nsAutoString descr;
mTable->RowDescription(aRowIdx, descr);
if (descr.IsEmpty())
return S_FALSE;
*aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
return *aDescription ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aSpan)
return E_INVALIDARG;
*aSpan = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || aColIdx < 0 ||
static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
*aSpan = mTable->RowExtentAt(aRowIdx, aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
long* aStartingColumnIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAccessibleTable || !aStartingColumnIndex)
return E_INVALIDARG;
*aAccessibleTable = nullptr;
*aStartingColumnIndex = -1;
return E_NOTIMPL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowIdx)
return E_INVALIDARG;
*aRowIdx = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aCellIdx < 0 ||
static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
return E_INVALIDARG;
*aRowIdx = mTable->RowIndexAt(aCellIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
long* aNChildren)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aChildren || !aNChildren)
return E_INVALIDARG;
*aChildren = nullptr;
*aNChildren = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
@@ -379,203 +321,159 @@ ia2AccessibleTable::get_selectedChildren
return S_FALSE;
*aChildren = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCells));
*aNChildren = maxCells;
for (uint32_t i = 0; i < maxCells; i++)
(*aChildren)[i] = cellIndices[i];
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedColumns(long aMaxColumns, long** aColumns,
long* aNColumns)
{
- A11Y_TRYBLOCK_BEGIN
-
return get_selectedColumns(aColumns, aNColumns);
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedRows(long aMaxRows, long** aRows, long* aNRows)
{
- A11Y_TRYBLOCK_BEGIN
-
return get_selectedRows(aRows, aNRows);
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_summary(IUnknown** aAccessible)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aAccessible)
return E_INVALIDARG;
// Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
// link an accessible object to specify a summary. There is closes method
// in Table::summary to get a summary as a string which is not mapped
// directly to IAccessible2.
*aAccessible = nullptr;
return S_FALSE;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIsSelected)
return E_INVALIDARG;
*aIsSelected = false;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
*aIsSelected = mTable->IsColSelected(aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIsSelected)
return E_INVALIDARG;
*aIsSelected = false;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
return E_INVALIDARG;
*aIsSelected = mTable->IsRowSelected(aRowIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIsSelected)
return E_INVALIDARG;
*aIsSelected = false;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || aColIdx < 0 ||
static_cast<uint32_t>(aColIdx) >= mTable->ColCount() ||
static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
return E_INVALIDARG;
*aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::selectRow(long aRowIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
return E_INVALIDARG;
mTable->SelectRow(aRowIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::selectColumn(long aColIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
mTable->SelectCol(aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::unselectRow(long aRowIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
return E_INVALIDARG;
mTable->UnselectRow(aRowIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::unselectColumn(long aColIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!mTable)
return CO_E_OBJNOTCONNECTED;
if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
return E_INVALIDARG;
mTable->UnselectCol(aColIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
long* aColIdx,
long* aRowExtents,
long* aColExtents,
boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
return E_INVALIDARG;
*aRowIdx = 0;
*aColIdx = 0;
*aRowExtents = 0;
*aColExtents = 0;
*aIsSelected = false;
@@ -590,76 +488,64 @@ ia2AccessibleTable::get_rowColumnExtents
mTable->RowAndColIndicesAt(aCellIdx, &rowIdx, &colIdx);
*aRowIdx = rowIdx;
*aColIdx = colIdx;
*aRowExtents = mTable->RowExtentAt(rowIdx, colIdx);
*aColExtents = mTable->ColExtentAt(rowIdx, colIdx);
*aIsSelected = mTable->IsCellSelected(rowIdx, colIdx);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_modelChange(IA2TableModelChange* aModelChange)
{
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////////
// IAccessibleTable2
STDMETHODIMP
ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCell)
return E_INVALIDARG;
*aCell = nullptr;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
AccessibleWrap* cell =
static_cast<AccessibleWrap*>(mTable->CellAt(aRowIdx, aColIdx));
if (!cell)
return E_INVALIDARG;
(*aCell = static_cast<IAccessible*>(cell))->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCellCount)
return E_INVALIDARG;
*aCellCount = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
*aCellCount = mTable->SelectedCellCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCells || !aNSelectedCells)
return E_INVALIDARG;
*aCells = nullptr;
*aNSelectedCells = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
@@ -677,25 +563,21 @@ ia2AccessibleTable::get_selectedCells(IU
for (uint32_t i = 0; i < cells.Length(); i++) {
(*aCells)[i] =
static_cast<IAccessible*>(static_cast<AccessibleWrap*>(cells[i]));
((*aCells)[i])->AddRef();
}
*aNSelectedCells = cells.Length();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aColumns || !aNColumns)
return E_INVALIDARG;
*aColumns = nullptr;
*aNColumns = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
@@ -707,25 +589,21 @@ ia2AccessibleTable::get_selectedColumns(
return S_FALSE;
*aColumns = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCols));
*aNColumns = maxCols;
for (uint32_t i = 0; i < maxCols; i++)
(*aColumns)[i] = colIndices[i];
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRows || !aNRows)
return E_INVALIDARG;
*aRows = nullptr;
*aNRows = 0;
if (!mTable)
return CO_E_OBJNOTCONNECTED;
@@ -737,11 +615,9 @@ ia2AccessibleTable::get_selectedRows(lon
return S_FALSE;
*aRows = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxRows));
*aNRows = maxRows;
for (uint32_t i = 0; i < maxRows; i++)
(*aRows)[i] = rowIndices[i];
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleTableCell.cpp
+++ b/accessible/windows/ia2/ia2AccessibleTableCell.cpp
@@ -41,62 +41,52 @@ ia2AccessibleTableCell::QueryInterface(R
}
////////////////////////////////////////////////////////////////////////////////
// IAccessibleTableCell
STDMETHODIMP
ia2AccessibleTableCell::get_table(IUnknown** aTable)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aTable)
return E_INVALIDARG;
*aTable = nullptr;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
TableAccessible* table = mTableCell->Table();
if (!table)
return E_FAIL;
AccessibleWrap* wrap = static_cast<AccessibleWrap*>(table->AsAccessible());
*aTable = static_cast<IAccessible*>(wrap);
(*aTable)->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_columnExtent(long* aSpan)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aSpan)
return E_INVALIDARG;
*aSpan = 0;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aSpan = mTableCell->ColExtent();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
long* aNColumnHeaderCells)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCellAccessibles || !aNColumnHeaderCells)
return E_INVALIDARG;
*aCellAccessibles = nullptr;
*aNColumnHeaderCells = 0;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
@@ -113,62 +103,50 @@ ia2AccessibleTableCell::get_columnHeader
for (uint32_t i = 0; i < cells.Length(); i++) {
AccessibleWrap* cell = static_cast<AccessibleWrap*>(cells[i]);
(*aCellAccessibles)[i] = static_cast<IAccessible*>(cell);
(*aCellAccessibles)[i]->AddRef();
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_columnIndex(long* aColIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aColIdx)
return E_INVALIDARG;
*aColIdx = -1;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aColIdx = mTableCell->ColIdx();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_rowExtent(long* aSpan)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aSpan)
return E_INVALIDARG;
*aSpan = 0;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aSpan = mTableCell->RowExtent();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
long* aNRowHeaderCells)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCellAccessibles || !aNRowHeaderCells)
return E_INVALIDARG;
*aCellAccessibles = nullptr;
*aNRowHeaderCells = 0;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
@@ -184,74 +162,60 @@ ia2AccessibleTableCell::get_rowHeaderCel
for (uint32_t i = 0; i < cells.Length(); i++) {
AccessibleWrap* cell = static_cast<AccessibleWrap*>(cells[i]);
(*aCellAccessibles)[i] = static_cast<IAccessible*>(cell);
(*aCellAccessibles)[i]->AddRef();
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_rowIndex(long* aRowIdx)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowIdx)
return E_INVALIDARG;
*aRowIdx = -1;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aRowIdx = mTableCell->RowIdx();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_rowColumnExtents(long* aRowIdx, long* aColIdx,
long* aRowExtents,
long* aColExtents,
boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
return E_INVALIDARG;
*aRowIdx = *aColIdx = *aRowExtents = *aColExtents = 0;
*aIsSelected = false;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aRowIdx = mTableCell->RowIdx();
*aColIdx = mTableCell->ColIdx();
*aRowExtents = mTableCell->RowExtent();
*aColExtents = mTableCell->ColExtent();
*aIsSelected = mTableCell->Selected();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleTableCell::get_isSelected(boolean* aIsSelected)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aIsSelected)
return E_INVALIDARG;
*aIsSelected = false;
if (!mTableCell)
return CO_E_OBJNOTCONNECTED;
*aIsSelected = mTableCell->Selected();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleText.cpp
@@ -23,36 +23,30 @@ uint32_t ia2AccessibleText::sLastTextCha
uint32_t ia2AccessibleText::sLastTextChangeEnd = 0;
bool ia2AccessibleText::sLastTextChangeWasInsert = false;
// IAccessibleText
STDMETHODIMP
ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
S_OK : E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
long *aEndOffset, BSTR *aTextAttributes)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStartOffset || !aEndOffset || !aTextAttributes)
return E_INVALIDARG;
*aStartOffset = 0;
*aEndOffset = 0;
*aTextAttributes = nullptr;
int32_t startOffset = 0, endOffset = 0;
@@ -69,51 +63,43 @@ ia2AccessibleText::get_attributes(long a
hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
if (FAILED(hr))
return hr;
*aStartOffset = startOffset;
*aEndOffset = endOffset;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_caretOffset(long *aOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aOffset)
return E_INVALIDARG;
*aOffset = -1;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct()) {
return CO_E_OBJNOTCONNECTED;
}
*aOffset = textAcc->CaretOffset();
return *aOffset != -1 ? S_OK : S_FALSE;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_characterExtents(long aOffset,
enum IA2CoordinateType aCoordType,
long* aX, long* aY,
long* aWidth, long* aHeight)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aX || !aY || !aWidth || !aHeight)
return E_INVALIDARG;
*aX = *aY = *aWidth = *aHeight = 0;
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
nsIntRect rect;
@@ -124,49 +110,41 @@ ia2AccessibleText::get_characterExtents(
rect = textAcc->CharBounds(aOffset, geckoCoordType);
*aX = rect.x;
*aY = rect.y;
*aWidth = rect.width;
*aHeight = rect.height;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_nSelections(long* aNSelections)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNSelections)
return E_INVALIDARG;
*aNSelections = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct()) {
return CO_E_OBJNOTCONNECTED;
}
*aNSelections = textAcc->SelectionCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
enum IA2CoordinateType aCoordType,
long* aOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aOffset)
return E_INVALIDARG;
*aOffset = 0;
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
@@ -174,26 +152,22 @@ ia2AccessibleText::get_offsetAtPoint(lon
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct()) {
return CO_E_OBJNOTCONNECTED;
}
*aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
return *aOffset == -1 ? S_FALSE : S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
long* aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStartOffset || !aEndOffset)
return E_INVALIDARG;
*aStartOffset = *aEndOffset = 0;
int32_t startOffset = 0, endOffset = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct()) {
@@ -202,25 +176,21 @@ ia2AccessibleText::get_selection(long aS
if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset)) {
return E_INVALIDARG;
}
*aStartOffset = startOffset;
*aEndOffset = endOffset;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aText)
return E_INVALIDARG;
*aText = nullptr;
nsAutoString text;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -234,28 +204,24 @@ ia2AccessibleText::get_text(long aStartO
textAcc->TextSubstring(aStartOffset, aEndOffset, text);
if (text.IsEmpty())
return S_FALSE;
*aText = ::SysAllocStringLen(text.get(), text.Length());
return *aText ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_textBeforeOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long* aStartOffset, long* aEndOffset,
BSTR* aText)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStartOffset || !aEndOffset || !aText)
return E_INVALIDARG;
*aStartOffset = *aEndOffset = 0;
*aText = nullptr;
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
@@ -282,28 +248,24 @@ ia2AccessibleText::get_textBeforeOffset(
*aStartOffset = startOffset;
*aEndOffset = endOffset;
if (text.IsEmpty())
return S_FALSE;
*aText = ::SysAllocStringLen(text.get(), text.Length());
return *aText ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_textAfterOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long* aStartOffset, long* aEndOffset,
BSTR* aText)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStartOffset || !aEndOffset || !aText)
return E_INVALIDARG;
*aStartOffset = 0;
*aEndOffset = 0;
*aText = nullptr;
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
@@ -330,28 +292,24 @@ ia2AccessibleText::get_textAfterOffset(l
*aStartOffset = startOffset;
*aEndOffset = endOffset;
if (text.IsEmpty())
return S_FALSE;
*aText = ::SysAllocStringLen(text.get(), text.Length());
return *aText ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_textAtOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long* aStartOffset, long* aEndOffset,
BSTR* aText)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aStartOffset || !aEndOffset || !aText)
return E_INVALIDARG;
*aStartOffset = *aEndOffset = 0;
*aText = nullptr;
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
@@ -376,162 +334,128 @@ ia2AccessibleText::get_textAtOffset(long
*aStartOffset = startOffset;
*aEndOffset = endOffset;
if (text.IsEmpty())
return S_FALSE;
*aText = ::SysAllocStringLen(text.get(), text.Length());
return *aText ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::removeSelection(long aSelectionIndex)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
return textAcc->RemoveFromSelection(aSelectionIndex) ?
S_OK : E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::setCaretOffset(long aOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidOffset(aOffset))
return E_INVALIDARG;
textAcc->SetCaretOffset(aOffset);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
long aEndOffset)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ?
S_OK : E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_nCharacters(long* aNCharacters)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aNCharacters)
return E_INVALIDARG;
*aNCharacters = 0;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
*aNCharacters = textAcc->CharacterCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
enum IA2ScrollType aScrollType)
{
- A11Y_TRYBLOCK_BEGIN
-
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
return E_INVALIDARG;
textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
enum IA2CoordinateType aCoordType,
long aX, long aY)
{
- A11Y_TRYBLOCK_BEGIN
-
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
MOZ_ASSERT(!HyperTextProxyFor(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
return E_INVALIDARG;
textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
geckoCoordType, aX, aY);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
{
- A11Y_TRYBLOCK_BEGIN
-
return GetModifiedText(true, aNewText);
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
{
- A11Y_TRYBLOCK_BEGIN
-
return GetModifiedText(false, aOldText);
-
- A11Y_TRYBLOCK_END
}
// ia2AccessibleText
HRESULT
ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
IA2TextSegment *aText)
{
--- a/accessible/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/windows/ia2/ia2AccessibleValue.cpp
@@ -41,18 +41,16 @@ ia2AccessibleValue::QueryInterface(REFII
return E_NOINTERFACE;
}
// IAccessibleValue
STDMETHODIMP
ia2AccessibleValue::get_currentValue(VARIANT* aCurrentValue)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aCurrentValue)
return E_INVALIDARG;
VariantInit(aCurrentValue);
AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
double currentValue;
MOZ_ASSERT(!valueAcc->IsProxy());
@@ -63,44 +61,36 @@ ia2AccessibleValue::get_currentValue(VAR
currentValue = valueAcc->CurValue();
if (IsNaN(currentValue))
return S_FALSE;
aCurrentValue->vt = VT_R8;
aCurrentValue->dblVal = currentValue;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleValue::setCurrentValue(VARIANT aValue)
{
- A11Y_TRYBLOCK_BEGIN
-
if (aValue.vt != VT_R8)
return E_INVALIDARG;
AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
MOZ_ASSERT(!valueAcc->IsProxy());
if (valueAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
return valueAcc->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aMaximumValue)
return E_INVALIDARG;
VariantInit(aMaximumValue);
AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
double maximumValue;
MOZ_ASSERT(!valueAcc->IsProxy());
@@ -111,25 +101,21 @@ ia2AccessibleValue::get_maximumValue(VAR
maximumValue = valueAcc->MaxValue();
if (IsNaN(maximumValue))
return S_FALSE;
aMaximumValue->vt = VT_R8;
aMaximumValue->dblVal = maximumValue;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
ia2AccessibleValue::get_minimumValue(VARIANT* aMinimumValue)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!aMinimumValue)
return E_INVALIDARG;
VariantInit(aMinimumValue);
AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
double minimumValue;
MOZ_ASSERT(!valueAcc->IsProxy());
@@ -140,12 +126,10 @@ ia2AccessibleValue::get_minimumValue(VAR
minimumValue = valueAcc->MinValue();
if (IsNaN(minimumValue))
return S_FALSE;
aMinimumValue->vt = VT_R8;
aMinimumValue->dblVal = minimumValue;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -4,20 +4,19 @@
* 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/. */
#include "AccessibleWrap.h"
#include "Accessible-inl.h"
#include "Compatibility.h"
#include "DocAccessible-inl.h"
-#include "mozilla/dom/TabChild.h"
-#include "mozilla/a11y/DocAccessibleChild.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "EnumVariant.h"
+#include "GeckoCustom.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsIAccessibleEvent.h"
#include "nsWinUtils.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "ProxyWrappers.h"
#include "ServiceProvider.h"
#include "Relation.h"
@@ -29,16 +28,17 @@
#ifdef A11Y_LOG
#include "Logging.h"
#endif
#include "nsIMutableArray.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "mozilla/dom/NodeInfo.h"
+#include "mozilla/dom/TabParent.h"
#include "nsIServiceManager.h"
#include "nsNameSpaceManager.h"
#include "nsTextFormatter.h"
#include "nsView.h"
#include "nsViewManager.h"
#include "nsEventMap.h"
#include "nsArrayUtils.h"
#include "mozilla/Preferences.h"
@@ -86,36 +86,35 @@ AccessibleWrap::~AccessibleWrap()
ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
void
AccessibleWrap::Shutdown()
{
if (mID != kNoID) {
- auto doc = static_cast<DocAccessibleWrap*>(mDoc);
+ auto doc = static_cast<DocAccessibleWrap*>(mDoc.get());
MOZ_ASSERT(doc);
if (doc) {
doc->RemoveID(mID);
+ mID = kNoID;
}
}
Accessible::Shutdown();
}
//-----------------------------------------------------
// IUnknown interface methods - see iunknown.h for documentation
//-----------------------------------------------------
// Microsoft COM QueryInterface
STDMETHODIMP
AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!ppv)
return E_INVALIDARG;
*ppv = nullptr;
if (IID_IUnknown == iid)
*ppv = static_cast<IAccessible*>(this);
else if (IID_IDispatch == iid || IID_IAccessible == iid)
@@ -154,34 +153,36 @@ AccessibleWrap::QueryInterface(REFIID ii
}
if (nullptr == *ppv && !IsProxy()) {
HRESULT hr = ia2AccessibleValue::QueryInterface(iid, ppv);
if (SUCCEEDED(hr))
return hr;
}
+ if (!*ppv && iid == IID_IGeckoCustom) {
+ RefPtr<GeckoCustom> gkCrap = new GeckoCustom(this);
+ gkCrap.forget(ppv);
+ return S_OK;
+ }
+
if (nullptr == *ppv)
return E_NOINTERFACE;
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
//-----------------------------------------------------
// IAccessible methods
//-----------------------------------------------------
STDMETHODIMP
AccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!ppdispParent)
return E_INVALIDARG;
*ppdispParent = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -202,49 +203,41 @@ AccessibleWrap::get_accParent( IDispatch
}
Accessible* xpParentAcc = Parent();
if (!xpParentAcc)
return S_FALSE;
*ppdispParent = NativeAccessible(xpParentAcc);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pcountChildren)
return E_INVALIDARG;
*pcountChildren = 0;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
if (nsAccUtils::MustPrune(this))
return S_OK;
*pcountChildren = ChildCount();
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!ppdispChild)
return E_INVALIDARG;
*ppdispChild = nullptr;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
// IAccessible::accChild is used to return this accessible or child accessible
@@ -259,18 +252,16 @@ AccessibleWrap::get_accChild(
}
if (isDefunct) {
return CO_E_OBJNOTCONNECTED;
}
child.forget(ppdispChild);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
/**
* This function is a helper for implementing IAccessible methods that accept
* a Child ID as a parameter. If the child ID is CHILDID_SELF, the function
* returns S_OK but a null *aOutInterface. Otherwise, *aOutInterface points
* to the resolved IAccessible.
*
@@ -325,18 +316,16 @@ AccessibleWrap::ResolveChild(const VARIA
return S_OK;
}
STDMETHODIMP
AccessibleWrap::get_accName(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszName)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszName || varChild.vt != VT_I4)
return E_INVALIDARG;
*pszName = nullptr;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -355,28 +344,24 @@ AccessibleWrap::get_accName(
// attribute. Refer to eNoNameOnPurpose return value.
if (name.IsVoid())
return S_FALSE;
*pszName = ::SysAllocStringLen(name.get(), name.Length());
if (!*pszName)
return E_OUTOFMEMORY;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accValue(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszValue)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszValue)
return E_INVALIDARG;
*pszValue = nullptr;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -395,26 +380,22 @@ AccessibleWrap::get_accValue(
// IAccessible2-style.
if (value.IsEmpty())
return S_FALSE;
*pszValue = ::SysAllocStringLen(value.get(), value.Length());
if (!*pszValue)
return E_OUTOFMEMORY;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accDescription(VARIANT varChild,
BSTR __RPC_FAR *pszDescription)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszDescription)
return E_INVALIDARG;
*pszDescription = nullptr;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -426,27 +407,23 @@ AccessibleWrap::get_accDescription(VARIA
}
nsAutoString description;
Description(description);
*pszDescription = ::SysAllocStringLen(description.get(),
description.Length());
return *pszDescription ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accRole(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarRole)
return E_INVALIDARG;
VariantInit(pvarRole);
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -526,27 +503,23 @@ AccessibleWrap::get_accRole(
if (!roleString.IsEmpty()) {
pvarRole->vt = VT_BSTR;
pvarRole->bstrVal = ::SysAllocString(roleString.get());
return S_OK;
}
}
return E_FAIL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accState(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ VARIANT __RPC_FAR *pvarState)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarState)
return E_INVALIDARG;
VariantInit(pvarState);
pvarState->vt = VT_I4;
pvarState->lVal = 0;
RefPtr<IAccessible> accessible;
@@ -568,62 +541,50 @@ AccessibleWrap::get_accState(
// CHECKABLE -> MARQUEED
uint64_t state = State();
uint32_t msaaState = 0;
nsAccUtils::To32States(state, &msaaState, nullptr);
pvarState->lVal = msaaState;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accHelp(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszHelp)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszHelp)
return E_INVALIDARG;
*pszHelp = nullptr;
return S_FALSE;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accHelpTopic(
/* [out] */ BSTR __RPC_FAR *pszHelpFile,
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ long __RPC_FAR *pidTopic)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszHelpFile || !pidTopic)
return E_INVALIDARG;
*pszHelpFile = nullptr;
*pidTopic = 0;
return S_FALSE;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accKeyboardShortcut(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszKeyboardShortcut)
return E_INVALIDARG;
*pszKeyboardShortcut = nullptr;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
@@ -639,26 +600,22 @@ AccessibleWrap::get_accKeyboardShortcut(
keyBinding = KeyboardShortcut();
nsAutoString shortcut;
keyBinding.ToString(shortcut);
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
shortcut.Length());
return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accFocus(
/* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarChild)
return E_INVALIDARG;
VariantInit(pvarChild);
// VT_EMPTY: None. This object does not have the keyboard focus itself
// and does not contain a child that has the keyboard focus.
// VT_I4: lVal is CHILDID_SELF. The object itself has the keyboard focus.
@@ -679,28 +636,26 @@ AccessibleWrap::get_accFocus(
pvarChild->vt = VT_DISPATCH;
pvarChild->pdispVal = NativeAccessible(focusedAccessible);
}
else {
pvarChild->vt = VT_EMPTY; // No focus or focus is not a child
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
/**
* This helper class implements IEnumVARIANT for a nsTArray containing
* accessible objects.
*/
class AccessibleEnumerator final : public IEnumVARIANT
{
public:
- AccessibleEnumerator(const nsTArray<Accessible*>& aArray) :
+ explicit AccessibleEnumerator(const nsTArray<Accessible*>& aArray) :
mArray(aArray), mCurIndex(0) { }
AccessibleEnumerator(const AccessibleEnumerator& toCopy) :
mArray(toCopy.mArray), mCurIndex(toCopy.mCurIndex) { }
~AccessibleEnumerator() { }
// IUnknown
DECL_IUNKNOWN
@@ -717,40 +672,34 @@ public:
private:
nsTArray<Accessible*> mArray;
uint32_t mCurIndex;
};
STDMETHODIMP
AccessibleEnumerator::QueryInterface(REFIID iid, void ** ppvObject)
{
- A11Y_TRYBLOCK_BEGIN
-
if (iid == IID_IEnumVARIANT) {
*ppvObject = static_cast<IEnumVARIANT*>(this);
AddRef();
return S_OK;
}
if (iid == IID_IUnknown) {
*ppvObject = static_cast<IUnknown*>(this);
AddRef();
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleEnumerator::Next(unsigned long celt, VARIANT FAR* rgvar, unsigned long FAR* pceltFetched)
{
- A11Y_TRYBLOCK_BEGIN
-
uint32_t length = mArray.Length();
HRESULT hr = S_OK;
// Can't get more elements than there are...
if (celt > length - mCurIndex) {
hr = S_FALSE;
celt = length - mCurIndex;
}
@@ -760,49 +709,39 @@ AccessibleEnumerator::Next(unsigned long
rgvar[i].vt = VT_DISPATCH;
rgvar[i].pdispVal = AccessibleWrap::NativeAccessible(mArray[mCurIndex]);
}
if (pceltFetched)
*pceltFetched = celt;
return hr;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleEnumerator::Clone(IEnumVARIANT FAR* FAR* ppenum)
{
- A11Y_TRYBLOCK_BEGIN
-
*ppenum = new AccessibleEnumerator(*this);
if (!*ppenum)
return E_OUTOFMEMORY;
NS_ADDREF(*ppenum);
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleEnumerator::Skip(unsigned long celt)
{
- A11Y_TRYBLOCK_BEGIN
-
uint32_t length = mArray.Length();
// Check if we can skip the requested number of elements
if (celt > length - mCurIndex) {
mCurIndex = length;
return S_FALSE;
}
mCurIndex += celt;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
/**
* This method is called when a client wants to know which children of a node
* are selected. Note that this method can only find selected children for
* accessible object which implement SelectAccessible.
*
* The VARIANT return value arguement is expected to either contain a single IAccessible
@@ -815,18 +754,16 @@ AccessibleEnumerator::Skip(unsigned long
*
* returns a VT_EMPTY VARIANT if:
* - there are no selected children for this object
* - the object is not the type that can have children selected
*/
STDMETHODIMP
AccessibleWrap::get_accSelection(VARIANT __RPC_FAR *pvarChildren)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarChildren)
return E_INVALIDARG;
VariantInit(pvarChildren);
pvarChildren->vt = VT_EMPTY;
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -836,27 +773,23 @@ AccessibleWrap::get_accSelection(VARIANT
SelectedItems(&selectedItems);
// 1) Create and initialize the enumeration
RefPtr<AccessibleEnumerator> pEnum = new AccessibleEnumerator(selectedItems);
pvarChildren->vt = VT_UNKNOWN; // this must be VT_UNKNOWN for an IEnumVARIANT
NS_ADDREF(pvarChildren->punkVal = pEnum);
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::get_accDefaultAction(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszDefaultAction)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pszDefaultAction)
return E_INVALIDARG;
*pszDefaultAction = nullptr;
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -868,27 +801,23 @@ AccessibleWrap::get_accDefaultAction(
}
nsAutoString defaultAction;
ActionNameAt(0, defaultAction);
*pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
defaultAction.Length());
return *pszDefaultAction ? S_OK : E_OUTOFMEMORY;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::accSelect(
/* [in] */ long flagsSelect,
/* [optional][in] */ VARIANT varChild)
{
- A11Y_TRYBLOCK_BEGIN
-
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
if (accessible) {
return accessible->accSelect(flagsSelect, kVarChildIdSelf);
@@ -920,30 +849,26 @@ AccessibleWrap::accSelect(
}
if (flagsSelect & SELFLAG_REMOVESELECTION) {
SetSelected(false);
return S_OK;
}
return E_FAIL;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::accLocation(
/* [out] */ long __RPC_FAR *pxLeft,
/* [out] */ long __RPC_FAR *pyTop,
/* [out] */ long __RPC_FAR *pcxWidth,
/* [out] */ long __RPC_FAR *pcyHeight,
/* [optional][in] */ VARIANT varChild)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pxLeft || !pyTop || !pcxWidth || !pcyHeight)
return E_INVALIDARG;
*pxLeft = 0;
*pyTop = 0;
*pcxWidth = 0;
*pcyHeight = 0;
@@ -960,28 +885,24 @@ AccessibleWrap::accLocation(
nsIntRect rect = Bounds();
*pxLeft = rect.x;
*pyTop = rect.y;
*pcxWidth = rect.width;
*pcyHeight = rect.height;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::accNavigate(
/* [in] */ long navDir,
/* [optional][in] */ VARIANT varStart,
/* [retval][out] */ VARIANT __RPC_FAR *pvarEndUpAt)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarEndUpAt)
return E_INVALIDARG;
VariantInit(pvarEndUpAt);
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varStart, getter_AddRefs(accessible));
if (FAILED(hr)) {
@@ -1054,28 +975,24 @@ AccessibleWrap::accNavigate(
}
if (!navAccessible)
return E_FAIL;
pvarEndUpAt->pdispVal = NativeAccessible(navAccessible);
pvarEndUpAt->vt = VT_DISPATCH;
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::accHitTest(
/* [in] */ long xLeft,
/* [in] */ long yTop,
/* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
{
- A11Y_TRYBLOCK_BEGIN
-
if (!pvarChild)
return E_INVALIDARG;
VariantInit(pvarChild);
if (IsDefunct())
return CO_E_OBJNOTCONNECTED;
@@ -1092,39 +1009,33 @@ AccessibleWrap::accHitTest(
pvarChild->pdispVal = NativeAccessible(accessible);
}
} else {
// no child at that point
pvarChild->vt = VT_EMPTY;
return S_FALSE;
}
return S_OK;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::accDoDefaultAction(
/* [optional][in] */ VARIANT varChild)
{
- A11Y_TRYBLOCK_BEGIN
-
RefPtr<IAccessible> accessible;
HRESULT hr = ResolveChild(varChild, getter_AddRefs(accessible));
if (FAILED(hr)) {
return hr;
}
if (accessible) {
return accessible->accDoDefaultAction(kVarChildIdSelf);
}
return DoAction(0) ? S_OK : E_INVALIDARG;
-
- A11Y_TRYBLOCK_END
}
STDMETHODIMP
AccessibleWrap::put_accName(
/* [optional][in] */ VARIANT varChild,
/* [in] */ BSTR szName)
{
return E_NOTIMPL;
@@ -1339,41 +1250,35 @@ AccessibleWrap::GetChildIDFor(Accessible
HWND
AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
{
if (!aAccessible) {
return nullptr;
}
- if (XRE_IsContentProcess()) {
- DocAccessible* doc = aAccessible->Document();
- if (!doc) {
- return nullptr;
- }
-
- DocAccessibleChild* ipcDoc = doc->IPCDoc();
- if (!ipcDoc) {
- return nullptr;
- }
-
- auto tab = static_cast<dom::TabChild*>(ipcDoc->Manager());
- MOZ_ASSERT(tab);
- return reinterpret_cast<HWND>(tab->GetNativeWindowHandle());
- }
-
- // Accessibles in child processes are said to have the HWND of the window
- // their tab is within. Popups are always in the parent process, and so
- // never proxied, which means this is basically correct.
if (aAccessible->IsProxy()) {
ProxyAccessible* proxy = aAccessible->Proxy();
if (!proxy) {
return nullptr;
}
+ // If window emulation is enabled, retrieve the emulated window from the
+ // containing document document proxy.
+ if (nsWinUtils::IsWindowEmulationStarted()) {
+ DocAccessibleParent* doc = proxy->Document();
+ HWND hWnd = doc->GetEmulatedWindowHandle();
+ if (hWnd) {
+ return hWnd;
+ }
+ }
+
+ // Accessibles in child processes are said to have the HWND of the window
+ // their tab is within. Popups are always in the parent process, and so
+ // never proxied, which means this is basically correct.
Accessible* outerDoc = proxy->OuterDocOfRemoteBrowser();
NS_ASSERTION(outerDoc, "no outer doc for accessible remote tab!");
if (!outerDoc) {
return nullptr;
}
return GetHWNDFor(outerDoc);
}
@@ -1437,31 +1342,45 @@ GetAccessibleInSubtree(DocAccessible* aD
}
static already_AddRefed<IDispatch>
GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc,
const VARIANT& aVarChild)
{
auto wrapper = static_cast<DocProxyAccessibleWrap*>(WrapperFor(aDoc));
RefPtr<IAccessible> comProxy;
- int32_t wrapperChildId = AccessibleWrap::GetChildIDFor(wrapper);
- if (wrapperChildId == aVarChild.lVal) {
+ int32_t docWrapperChildId = AccessibleWrap::GetChildIDFor(wrapper);
+ // Only top level document accessible proxies are created with a pointer to
+ // their COM proxy.
+ if (aDoc->IsTopLevel()) {
wrapper->GetNativeInterface(getter_AddRefs(comProxy));
- return comProxy.forget();
+ } else {
+ auto tab = static_cast<dom::TabParent*>(aDoc->Manager());
+ MOZ_ASSERT(tab);
+ DocAccessibleParent* topLevelDoc = tab->GetTopLevelDocAccessible();
+ MOZ_ASSERT(topLevelDoc && topLevelDoc->IsTopLevel());
+ VARIANT docId = {VT_I4};
+ docId.lVal = docWrapperChildId;
+ RefPtr<IDispatch> disp = GetProxiedAccessibleInSubtree(topLevelDoc, docId);
+ if (!disp) {
+ return nullptr;
+ }
+
+ DebugOnly<HRESULT> hr = disp->QueryInterface(IID_IAccessible,
+ getter_AddRefs(comProxy));
+ MOZ_ASSERT(SUCCEEDED(hr));
}
- MOZ_ASSERT(aDoc->IsTopLevel());
- if (!aDoc->IsTopLevel()) {
+ MOZ_ASSERT(comProxy);
+ if (!comProxy) {
return nullptr;
}
- wrapper->GetNativeInterface(getter_AddRefs(comProxy));
- MOZ_ASSERT(comProxy);
- if (!comProxy) {
- return nullptr;
+ if (docWrapperChildId == aVarChild.lVal) {
+ return comProxy.forget();
}
RefPtr<IDispatch> disp;
if (FAILED(comProxy->get_accChild(aVarChild, getter_AddRefs(disp)))) {
return nullptr;
}
return disp.forget();
@@ -1495,23 +1414,28 @@ AccessibleWrap::GetIAccessibleFor(const
return nullptr;
}
// Otherwise, since we're a proxy and we have a null native interface, this
// indicates that we need to obtain a COM proxy. To do this, we'll replace
// CHILDID_SELF with our real MSAA ID and continue the search from there.
varChild.lVal = GetExistingID();
}
- if (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this)) {
+ if (varChild.ulVal != GetExistingID() &&
+ (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this))) {
+ // This accessible should have no subtree in platform, return null for its children.
return nullptr;
}
// If the MSAA ID is not a chrome id then we already know that we won't
- // find it here and should look remotely instead.
- if (XRE_IsParentProcess() && !sIDGen.IsChromeID(varChild.lVal)) {
+ // find it here and should look remotely instead. This handles the case when
+ // accessible is part of the chrome process and is part of the xul browser
+ // window and the child id points in the content documents. Thus we need to
+ // make sure that it is never called on proxies.
+ if (XRE_IsParentProcess() && !IsProxy() && !sIDGen.IsChromeID(varChild.lVal)) {
return GetRemoteIAccessibleFor(varChild);
}
MOZ_ASSERT(XRE_IsParentProcess() ||
sIDGen.IsIDForThisContentProcess(varChild.lVal));
if (varChild.lVal > 0) {
// Gecko child indices are 0-based in contrast to indices used in MSAA.
MOZ_ASSERT(!IsProxy());
@@ -1572,17 +1496,16 @@ AccessibleWrap::GetIAccessibleFor(const
}
return