Merge m-c to oak
authorMatt Howell <mhowell@mozilla.com>
Wed, 24 Aug 2016 09:17:59 -0700
changeset 491561 784a79963dabb28544137c479cbb640d40cd4e4c
parent 491560 4afd44e5b901a945baa58d979a4576aa2e16bd40 (current diff)
parent 404988 01748a2b1a463f24efd9cd8abad9ccfd76b037b8 (diff)
child 491562 189f55e63199a739681870427df90cb1bc4e57f5
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
bugs1246972
milestone51.0a1
Merge m-c to oak This is to create a build for testing updating from a build with bug 1246972 applied.
CLOBBER
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
b2g/app/b2g.js
b2g/components/MobileIdentityUIGlue.js
b2g/components/PaymentGlue.js
b2g/components/PaymentProviderStrategy.js
b2g/installer/Makefile.in
b2g/installer/package-manifest.in
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/base/content/chatWindow.xul
browser/base/content/socialchat.xml
browser/base/content/socialmarks.xml
browser/base/content/test/chat/.eslintrc
browser/base/content/test/chat/browser.ini
browser/base/content/test/chat/browser_chatwindow.js
browser/base/content/test/chat/browser_focus.js
browser/base/content/test/chat/browser_tearoff.js
browser/base/content/test/chat/chat.html
browser/base/content/test/chat/head.js
browser/base/content/test/social/browser_social_chatwindow.js
browser/base/content/test/social/browser_social_chatwindow_resize.js
browser/base/content/test/social/browser_social_chatwindowfocus.js
browser/base/content/test/social/browser_social_contextmenu.js
browser/base/content/test/social/browser_social_errorPage.js
browser/base/content/test/social/browser_social_flyout.js
browser/base/content/test/social/browser_social_isVisible.js
browser/base/content/test/social/browser_social_marks.js
browser/base/content/test/social/browser_social_marks_context.js
browser/base/content/test/social/browser_social_multiprovider.js
browser/base/content/test/social/browser_social_sidebar.js
browser/base/content/test/social/browser_social_status.js
browser/base/content/test/social/browser_social_window.js
browser/base/content/test/social/checked.jpg
browser/base/content/test/social/social_chat.html
browser/base/content/test/social/social_flyout.html
browser/base/content/test/social/social_mark.html
browser/base/content/test/social/social_panel.html
browser/base/content/test/social/social_sidebar.html
browser/base/content/test/social/social_sidebar_empty.html
browser/base/content/test/social/unchecked.jpg
browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
browser/components/preferences/in-content/advanced.js
browser/config/mozconfigs/linux32/debug
browser/config/mozconfigs/linux64/debug
browser/config/mozconfigs/macosx64/debug
browser/config/mozconfigs/macosx64/nightly
browser/config/mozconfigs/win32/debug
browser/config/mozconfigs/win64/debug
browser/confvars.sh
browser/installer/package-manifest.in
browser/modules/Chat.jsm
browser/themes/shared/social/chat-icons.svg
browser/themes/shared/social/chat.inc.css
configure.in
devtools/client/inspector/inspector.css
devtools/client/locales/en-US/animationinspector.dtd
devtools/client/netmonitor/test/html_har_post-data-test-page.html
devtools/client/styleeditor/styleeditor.css
devtools/client/webconsole/new-console-output/components/filter-toggle-button.js
devtools/client/webconsole/new-console-output/test/actions/head.js
devtools/client/webconsole/new-console-output/test/actions/test_messages.js
devtools/client/webconsole/new-console-output/test/actions/xpcshell.ini
devtools/client/webconsole/new-console-output/test/components/chrome.ini
devtools/client/webconsole/new-console-output/test/components/head.js
devtools/client/webconsole/new-console-output/test/components/test_console-api-call.html
devtools/client/webconsole/new-console-output/test/components/test_console-api-call_repeat.html
devtools/client/webconsole/new-console-output/test/components/test_evaluation-result.html
devtools/client/webconsole/new-console-output/test/components/test_message-container.html
devtools/client/webconsole/new-console-output/test/components/test_message-icon.html
devtools/client/webconsole/new-console-output/test/components/test_message-repeat.html
devtools/client/webconsole/new-console-output/test/components/test_page-error.html
devtools/client/webconsole/new-console-output/test/store/head.js
devtools/client/webconsole/new-console-output/test/store/test_messages.js
devtools/client/webconsole/new-console-output/test/store/xpcshell.ini
devtools/client/webconsole/new-console-output/test/stubs.js
devtools/client/webconsole/new-console-output/test/utils/chrome.ini
devtools/client/webconsole/new-console-output/test/utils/test_getRepeatId.html
devtools/client/webconsole/new-console-output/test/utils/test_render_perf.html
devtools/client/webconsole/test/browser_console_clear_method.js
dom/animation/Animation.cpp
dom/animation/Animation.h
dom/base/test/file_bug1268962.sjs
dom/base/test/test_bug1268962.html
dom/events/test/pointerevents/pointerevent_button_attribute_mouse-manual.html
dom/events/test/pointerevents/test_pointerevent_button_attribute_mouse-manual.html
dom/filesystem/compat/DOMFileSystem.cpp
dom/filesystem/compat/DOMFileSystem.h
dom/filesystem/compat/DirectoryEntry.cpp
dom/filesystem/compat/DirectoryEntry.h
dom/filesystem/compat/DirectoryReader.cpp
dom/filesystem/compat/DirectoryReader.h
dom/filesystem/compat/Entry.cpp
dom/filesystem/compat/Entry.h
dom/filesystem/compat/FileEntry.cpp
dom/filesystem/compat/FileEntry.h
dom/filesystem/compat/RootDirectoryEntry.cpp
dom/filesystem/compat/RootDirectoryEntry.h
dom/filesystem/compat/RootDirectoryReader.cpp
dom/filesystem/compat/RootDirectoryReader.h
dom/media/RtspMediaResource.cpp
dom/media/RtspMediaResource.h
dom/media/omx/RtspExtractor.cpp
dom/media/omx/RtspExtractor.h
dom/media/omx/RtspOmxDecoder.cpp
dom/media/omx/RtspOmxDecoder.h
dom/media/omx/RtspOmxReader.cpp
dom/media/omx/RtspOmxReader.h
dom/media/webaudio/test/test_disconnectAll.html
dom/media/webaudio/test/test_disconnectAudioParam.html
dom/media/webaudio/test/test_disconnectAudioParamFromOutput.html
dom/media/webaudio/test/test_disconnectExceptions.html
dom/media/webaudio/test/test_disconnectFromAudioNode.html
dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutput.html
dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutputAndInput.html
dom/media/webaudio/test/test_disconnectFromOutput.html
dom/mobileid/MobileIdentity.js
dom/mobileid/MobileIdentity.manifest
dom/mobileid/interfaces/moz.build
dom/mobileid/interfaces/nsIMobileIdentityService.idl
dom/mobileid/moz.build
dom/mobileid/test/mochitest.ini
dom/mobileid/test/test_mobileid_basics.html
dom/mobileid/test/test_mobileid_no_permission.html
dom/payment/Payment.js
dom/payment/Payment.jsm
dom/payment/Payment.manifest
dom/payment/PaymentFlowInfo.js
dom/payment/PaymentProvider.js
dom/payment/PaymentProviderUtils.cpp
dom/payment/PaymentProviderUtils.h
dom/payment/interfaces/moz.build
dom/payment/interfaces/nsIPaymentContentHelperService.idl
dom/payment/interfaces/nsIPaymentFlowInfo.idl
dom/payment/interfaces/nsIPaymentProviderStrategy.idl
dom/payment/interfaces/nsIPaymentUIGlue.idl
dom/payment/moz.build
dom/payment/tests/mochitest/MockPaymentsUIChromeScript.js
dom/payment/tests/mochitest/file_mozpayproviderchecker.html
dom/payment/tests/mochitest/file_payproviderfailure.html
dom/payment/tests/mochitest/file_payprovidersuccess.html
dom/payment/tests/mochitest/mochitest.ini
dom/payment/tests/mochitest/test_mozpay_callbacks.html
dom/payment/tests/mochitest/test_mozpaymentprovider.html
dom/payment/tests/unit/header_helper.js
dom/payment/tests/unit/test_paymanager_get_payment_request.js
dom/payment/tests/unit/xpcshell.ini
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
dom/vr/VRDevice.cpp
dom/vr/VRDevice.h
dom/webidl/DOMFileSystem.webidl
dom/webidl/MozPaymentProvider.webidl
dom/webidl/VRDevice.webidl
gfx/layers/d3d11/CompositorD3D11ShadersVR.h
gfx/layers/d3d11/CompositorD3D11VR.hlsl
gfx/layers/opengl/CompositorOGLVR.cpp
gfx/vr/VRDeviceProxy.cpp
gfx/vr/VRDeviceProxy.h
gfx/vr/VRDeviceProxyOrientationFallBack.cpp
gfx/vr/VRDeviceProxyOrientationFallBack.h
gfx/vr/gfxVRCardboard.cpp
gfx/vr/gfxVRCardboard.h
gfx/vr/gfxVROculus050.cpp
gfx/vr/gfxVROculus050.h
gfx/vr/ovr_capi_dynamic050.h
ipc/glue/GeckoChildProcessHost.cpp
js/src/jslock.h
js/src/proxy/DirectProxyHandler.cpp
js/xpconnect/src/XPCShellImpl.cpp
layout/reftests/css-invalid/input/input-maxlength-invalid.html
layout/reftests/css-invalid/input/input-maxlength-valid.html
layout/reftests/css-invalid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-invalid/textarea/textarea-maxlength-valid.html
layout/reftests/css-ui-invalid/input/input-maxlength-invalid-changed.html
layout/reftests/css-ui-invalid/input/input-maxlength-invalid-default.html
layout/reftests/css-ui-invalid/input/input-maxlength-valid.html
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-default-value-invalid.html
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-valid.html
layout/reftests/css-ui-valid/input/input-maxlength-invalid.html
layout/reftests/css-ui-valid/input/input-maxlength-valid-changed.html
layout/reftests/css-ui-valid/input/input-maxlength-valid.html
layout/reftests/css-ui-valid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid-changed.html
layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid.html
layout/reftests/css-valid/input/input-maxlength-invalid.html
layout/reftests/css-valid/input/input-maxlength-valid.html
layout/reftests/css-valid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-valid/textarea/textarea-maxlength-valid.html
layout/style/nsCSSProperty.h
layout/style/nsCSSPropertySet.h
media/libstagefright/binding/byteorder-mod.patch
media/libstagefright/binding/mp4parse-mod.patch
media/libstagefright/binding/mp4parse/src/byteorder/mod.rs
media/libstagefright/binding/mp4parse/src/byteorder/new.rs
mfbt/Snprintf.h
mobile/android/base/resources/drawable/scrollbar.png
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEvent.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/Layer.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/PluginLayer.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/TextureGenerator.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/TextureReaper.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/TouchEventHandler.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/VirtualLayer.java
mobile/android/tests/browser/robocop/roboextender/base/paymentsUI.html
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMozPay.java
mobile/android/tests/browser/robocop/testMozPay.js
mobile/android/themes/core/scrollbar-nonapz.css
netwerk/base/nsISecretDecoderRing.idl
netwerk/protocol/rtsp/RtspChannelChild.cpp
netwerk/protocol/rtsp/RtspChannelChild.h
netwerk/protocol/rtsp/RtspChannelParent.cpp
netwerk/protocol/rtsp/RtspChannelParent.h
netwerk/protocol/rtsp/RtspHandler.cpp
netwerk/protocol/rtsp/RtspHandler.h
netwerk/protocol/rtsp/controller/RtspController.cpp
netwerk/protocol/rtsp/controller/RtspController.h
netwerk/protocol/rtsp/controller/RtspControllerChild.cpp
netwerk/protocol/rtsp/controller/RtspControllerChild.h
netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
netwerk/protocol/rtsp/controller/RtspControllerParent.h
netwerk/protocol/rtsp/controller/RtspMetaData.cpp
netwerk/protocol/rtsp/controller/RtspMetaData.h
netwerk/protocol/rtsp/moz.build
netwerk/protocol/rtsp/rtsp/AAMRAssembler.cpp
netwerk/protocol/rtsp/rtsp/AAMRAssembler.h
netwerk/protocol/rtsp/rtsp/AAVCAssembler.cpp
netwerk/protocol/rtsp/rtsp/AAVCAssembler.h
netwerk/protocol/rtsp/rtsp/AH263Assembler.cpp
netwerk/protocol/rtsp/rtsp/AH263Assembler.h
netwerk/protocol/rtsp/rtsp/AMPEG4AudioAssembler.cpp
netwerk/protocol/rtsp/rtsp/AMPEG4AudioAssembler.h
netwerk/protocol/rtsp/rtsp/AMPEG4ElementaryAssembler.cpp
netwerk/protocol/rtsp/rtsp/AMPEG4ElementaryAssembler.h
netwerk/protocol/rtsp/rtsp/APacketSource.cpp
netwerk/protocol/rtsp/rtsp/APacketSource.h
netwerk/protocol/rtsp/rtsp/ARTPAssembler.cpp
netwerk/protocol/rtsp/rtsp/ARTPAssembler.h
netwerk/protocol/rtsp/rtsp/ARTPConnection.cpp
netwerk/protocol/rtsp/rtsp/ARTPConnection.h
netwerk/protocol/rtsp/rtsp/ARTPSession.cpp
netwerk/protocol/rtsp/rtsp/ARTPSession.h
netwerk/protocol/rtsp/rtsp/ARTPSource.cpp
netwerk/protocol/rtsp/rtsp/ARTPSource.h
netwerk/protocol/rtsp/rtsp/ARTPWriter.cpp
netwerk/protocol/rtsp/rtsp/ARTPWriter.h
netwerk/protocol/rtsp/rtsp/ARTSPConnection.cpp
netwerk/protocol/rtsp/rtsp/ARTSPConnection.h
netwerk/protocol/rtsp/rtsp/ARawAudioAssembler.cpp
netwerk/protocol/rtsp/rtsp/ARawAudioAssembler.h
netwerk/protocol/rtsp/rtsp/ASessionDescription.cpp
netwerk/protocol/rtsp/rtsp/ASessionDescription.h
netwerk/protocol/rtsp/rtsp/RTSPConnectionHandler.h
netwerk/protocol/rtsp/rtsp/RTSPSource.cpp
netwerk/protocol/rtsp/rtsp/RTSPSource.h
netwerk/protocol/rtsp/rtsp/RTSPTransmitter.h
netwerk/protocol/rtsp/rtsp/RtspPrlog.h
netwerk/protocol/rtsp/rtsp/UDPPusher.cpp
netwerk/protocol/rtsp/rtsp/UDPPusher.h
netwerk/protocol/rtsp/rtsp/VideoSource.h
netwerk/protocol/rtsp/rtsp/rtp_test.cpp
netwerk/test/unit_ipc/child_tracable_listener.js
netwerk/test/unit_ipc/test_traceable_channel_decoded_data.js
netwerk/test/unit_ipc/test_traceable_channel_modify_response.js
old-configure.in
python/mozbuild/mozbuild/base.py
python/virtualenv/virtualenv_support/pip-8.1.1-py2.py3-none-any.whl
python/virtualenv/virtualenv_support/setuptools-20.3-py2.py3-none-any.whl
rdf/tests/rdfcat/moz.build
rdf/tests/rdfcat/rdfcat.cpp
rdf/tests/rdfpoll/moz.build
rdf/tests/rdfpoll/rdfpoll.cpp
rdf/tests/triplescat/moz.build
rdf/tests/triplescat/triplescat.cpp
security/manager/ssl/nsSDR.cpp
security/manager/ssl/nsSDR.h
security/manager/ssl/tests/unit/head_psm.js
security/nss/.taskcluster.yml
security/nss/automation/taskcluster/graph/linux/build64-lsan.yml
security/nss/automation/taskcluster/graph/tests/memleak.yml
services/mobileid/MobileIdentityClient.jsm
services/mobileid/MobileIdentityCommon.jsm
services/mobileid/MobileIdentityCredentialsStore.jsm
services/mobileid/MobileIdentityManager.jsm
services/mobileid/MobileIdentitySmsMoMtVerificationFlow.jsm
services/mobileid/MobileIdentitySmsMtVerificationFlow.jsm
services/mobileid/MobileIdentitySmsVerificationFlow.jsm
services/mobileid/MobileIdentityUIGlueCommon.jsm
services/mobileid/MobileIdentityVerificationFlow.jsm
services/mobileid/interfaces/moz.build
services/mobileid/interfaces/nsIMobileIdentityUIGlue.idl
services/mobileid/moz.build
services/mobileid/tests/xpcshell/head.js
services/mobileid/tests/xpcshell/test_mobileid_client.js
services/mobileid/tests/xpcshell/test_mobileid_manager.js
services/mobileid/tests/xpcshell/test_mobileid_verification_flow.js
services/mobileid/tests/xpcshell/xpcshell.ini
testing/marionette/harness/marionette/tests/unit/test_selected.py
testing/marionette/harness/marionette/tests/unit/test_selected_chrome.py
testing/web-platform/meta/dom/ranges/Range-insertNode.html.ini
testing/web-platform/meta/dom/ranges/Range-surroundContents.html.ini
testing/web-platform/meta/html/semantics/embedded-content/the-img-element/invalid-src.html.ini
testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-tooShort.html.ini
testing/web-platform/meta/media-source/mediasource-append-buffer.html.ini
testing/web-platform/meta/media-source/mediasource-buffered.html.ini
testing/web-platform/meta/media-source/mediasource-liveseekable.html.ini
testing/web-platform/meta/media-source/mediasource-preload.html.ini
testing/web-platform/meta/media-source/mediasource-remove.html.ini
testing/web-platform/meta/media-source/mediasource-seek-during-pending-seek.html.ini
testing/web-platform/meta/media-source/mediasource-sequencemode-append-buffer.html.ini
toolkit/components/downloads/csd.pb.cc
toolkit/components/downloads/csd.pb.h
toolkit/components/downloads/csd.proto
toolkit/components/satchel/AutoCompleteE10S.jsm
toolkit/components/social/MozSocialAPI.jsm
toolkit/components/social/SocialService.jsm
toolkit/components/social/moz.build
toolkit/components/social/test/xpcshell/blocklist.xml
toolkit/components/social/test/xpcshell/head.js
toolkit/components/social/test/xpcshell/test_SocialService.js
toolkit/components/social/test/xpcshell/test_SocialServiceMigration21.js
toolkit/components/social/test/xpcshell/test_SocialServiceMigration22.js
toolkit/components/social/test/xpcshell/test_SocialServiceMigration29.js
toolkit/components/social/test/xpcshell/xpcshell.ini
toolkit/components/telemetry/Histograms.json
toolkit/crashreporter/CrashSubmit.jsm
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/locales/en-US/chrome/mozapps/update/updates.dtd
toolkit/mozapps/update/UpdateTelemetry.jsm
toolkit/mozapps/update/content/updates.js
toolkit/mozapps/update/content/updates.xul
toolkit/mozapps/update/nsIUpdateService.idl
toolkit/mozapps/update/nsUpdateService.js
toolkit/mozapps/update/tests/chrome/test_0081_error_patchApplyFailure_partial_only.xul
toolkit/mozapps/update/tests/chrome/test_0082_error_patchApplyFailure_complete_only.xul
toolkit/mozapps/update/tests/chrome/test_0083_error_patchApplyFailure_partial_complete.xul
toolkit/mozapps/update/tests/chrome/test_0084_error_patchApplyFailure_verify_failed.xul
toolkit/mozapps/update/tests/chrome/test_0121_check_requireBuiltinCert.xul
toolkit/mozapps/update/tests/chrome/test_0122_check_allowNonBuiltinCert_validCertAttrs.xul
toolkit/mozapps/update/tests/chrome/test_0123_check_allowNonBuiltinCert_noCertAttrsCheck.xul
toolkit/mozapps/update/tests/chrome/test_0131_check_invalidCertAttrs_noUpdate.xul
toolkit/mozapps/update/tests/chrome/test_0132_check_invalidCertAttrs_hasUpdate.xul
toolkit/mozapps/update/tests/chrome/test_0141_notify_invalidCertAttrs_noUpdate.xul
toolkit/mozapps/update/tests/chrome/test_0142_notify_invalidCertAttrs_hasUpdate.xul
toolkit/mozapps/update/tests/chrome/utils.js
toolkit/mozapps/update/tests/data/shared.js
toolkit/mozapps/update/tests/data/sharedUpdateXML.js
toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
toolkit/mozapps/update/tests/unit_aus_update/downloadAndHashCheckMar.js
toolkit/mozapps/update/tests/unit_aus_update/downloadInterruptedByOfflineRetry.js
toolkit/mozapps/update/tests/unit_aus_update/updateCheckOnLoadOnErrorStatusText.js
toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js
toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateAppBinInUseStageSuccess_win.js
toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js
toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSuccess.js
toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js
toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js
toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js
toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js
toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js
toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js
toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js
toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js
toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js
toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js
toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js
toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js
toolkit/mozapps/update/tests/unit_service_updater/marAppApplyDirLockedStageFailureSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marAppApplyUpdateAppBinInUseStageSuccessSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marAppApplyUpdateStageSuccessSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marAppApplyUpdateSuccessSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marAppInUseStageFailureCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marAppInUseSuccessCompleteSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessPartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessPartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFailurePartialSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailureCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailurePartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessPartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailureCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailurePartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailureCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailurePartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailureCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailurePartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessCompleteSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessPartialSvc_win.js
toolkit/mozapps/update/tests/unit_service_updater/marStageFailurePartialSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marStageSuccessCompleteSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marStageSuccessPartialSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marSuccessCompleteSvc.js
toolkit/mozapps/update/tests/unit_service_updater/marSuccessPartialSvc.js
toolkit/mozapps/update/updater/launchchild_osx.mm
toolkit/mozapps/update/updater/updater.cpp
toolkit/xre/MacLaunchHelper.mm
toolkit/xre/moz.build
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsUpdateDriver.cpp
toolkit/xre/nsXREDirProvider.cpp
xpcom/build/XPCOMInit.cpp
xpcom/tests/TestPipe.cpp
--- a/.eslintignore
+++ b/.eslintignore
@@ -59,20 +59,18 @@ b2g/locales/en-US/b2g-l10n.js
 browser/app/**
 browser/base/content/browser-social.js
 browser/base/content/nsContextMenu.js
 browser/base/content/sanitizeDialog.js
 browser/base/content/test/**
 browser/base/content/newtab/**
 browser/components/downloads/**
 browser/components/feeds/**
-browser/components/preferences/**
 browser/components/privatebrowsing/**
 browser/components/sessionstore/**
-browser/components/shell/**
 browser/components/tabview/**
 browser/components/translation/**
 browser/extensions/pdfjs/**
 browser/extensions/pocket/content/panels/js/vendor/**
 browser/locales/**
 
 # devtools/ exclusions
 devtools/client/canvasdebugger/**
@@ -109,16 +107,17 @@ devtools/client/webide/**
 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/inspector.js
+!devtools/server/actors/highlighters/css-grid.js
 !devtools/server/actors/highlighters/eye-dropper.js
 !devtools/server/actors/webbrowser.js
 !devtools/server/actors/webextension.js
 !devtools/server/actors/styles.js
 !devtools/server/actors/string.js
 !devtools/server/actors/csscoverage.js
 devtools/server/performance/**
 devtools/server/tests/**
@@ -137,16 +136,17 @@ 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
@@ -233,17 +233,16 @@ toolkit/modules/tests/xpcshell/test_task
 toolkit/components/osfile/**
 
 # External code:
 toolkit/components/microformats/test/**
 toolkit/components/reader/Readability.js
 toolkit/components/reader/JSDOMParser.js
 
 # Uses preprocessing
-toolkit/content/widgets/videocontrols.xml
 toolkit/content/widgets/wizard.xml
 toolkit/components/jsdownloads/src/DownloadIntegration.jsm
 toolkit/components/search/nsSearchService.js
 toolkit/components/url-classifier/**
 toolkit/components/urlformatter/nsURLFormatter.js
 toolkit/identity/FirefoxAccounts.jsm
 toolkit/modules/AppConstants.jsm
 toolkit/mozapps/downloads/nsHelperAppDlg.js
--- a/.gitignore
+++ b/.gitignore
@@ -69,16 +69,19 @@ parser/html/java/javaparser/
 python/psutil/**/*.so
 python/psutil/**/*.pyd
 python/psutil/build/
 
 # Ignore chrome.manifest files from the devtools loader
 devtools/client/chrome.manifest
 devtools/shared/chrome.manifest
 
+# Ignore node_modules directories in devtools
+devtools/client/**/node_modules
+
 # Tag files generated by GNU Global
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
 # Git clone directory for updating web-platform-tests
 testing/web-platform/sync/
--- a/.hgignore
+++ b/.hgignore
@@ -73,16 +73,19 @@
 
 # Git repositories
 .git/
 
 # Ignore chrome.manifest files from the devtools loader
 ^devtools/client/chrome.manifest$
 ^devtools/shared/chrome.manifest$
 
+# Ignore node_modules directories in devtools
+^devtools/client/.*/node_modules/
+
 # git checkout of libstagefright
 ^media/libstagefright/android$
 
 # Tag files generated by GNU Global
 GTAGS
 GRTAGS
 GSYMS
 GPATH
--- 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 1291229 - clobber due to changes in generated code (bug 1182840)
+Bug 1294803's backout needed a clobber to fix SM builds
--- a/Makefile.in
+++ b/Makefile.in
@@ -314,17 +314,17 @@ ifdef MOZ_CRASHREPORTER
 	echo packing symbols
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
 	cd $(DIST)/crashreporter-symbols && \
           zip -r5D '../$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip' . -x '*test*' -x '*Test*'
 	cd $(DIST)/crashreporter-symbols && \
 	grep 'sym' $(SYMBOL_INDEX_NAME) > $(SYMBOL_INDEX_NAME).tmp && \
 	  mv $(SYMBOL_INDEX_NAME).tmp $(SYMBOL_INDEX_NAME)
 	cd $(DIST)/crashreporter-symbols && \
-          zip -r5D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
+          zip -r5D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
 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
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -22,17 +22,17 @@
 #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/Snprintf.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 =
@@ -431,17 +431,17 @@ GetMaiAtkType(uint16_t interfacesBits)
 static const char*
 GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
 {
 #define MAI_ATK_TYPE_NAME_LEN (30)     /* 10+sizeof(uint16_t)*8/4+1 < 30 */
 
     static gchar namePrefix[] = "MaiAtkType";   /* size = 10 */
     static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];
 
-    snprintf_literal(name, "%s%x", namePrefix, interfacesBits);
+    SprintfLiteral(name, "%s%x", namePrefix, interfacesBits);
     name[MAI_ATK_TYPE_NAME_LEN] = '\0';
 
     return name;
 }
 
 bool
 AccessibleWrap::IsValidObject()
 {
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -31,16 +31,17 @@ SOURCES += [
     'UtilInterface.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/ipc',
+    '/accessible/ipc/other',
     '/accessible/xpcom',
     '/accessible/xul',
     '/other-licenses/atk-1.0',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -192,16 +192,26 @@ static const nsRoleMapEntry sWAIRoleMaps
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eReadonlyUntilEditable
   },
+  { // feed
+    &nsGkAtoms::feed,
+    roles::GROUPING,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
   { // form
     &nsGkAtoms::form,
     roles::FORM,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -510,16 +510,21 @@ DocManager::CreateDocOrRootAccessible(ns
         // 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)
+          IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
+          ipcDoc->SendCOMProxy(holder);
+#endif
         }
       }
     }
   } else {
     parentDocAcc->BindChildDocument(docAcc);
   }
 
 #ifdef A11Y_LOG
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -670,51 +670,51 @@ logging::TreeInfo(const char* aMsg, uint
       AccessibleInfo("child", aParent->GetChildAt(idx));
     }
     MsgEnd();
   }
 }
 
 void
 logging::Tree(const char* aTitle, const char* aMsgText,
-              DocAccessible* aDocument, GetTreePrefix aPrefixFunc,
+              Accessible* aRoot, GetTreePrefix aPrefixFunc,
               void* aGetTreePrefixData)
 {
   logging::MsgBegin(aTitle, aMsgText);
 
   nsAutoString level;
-  Accessible* root = aDocument;
+  Accessible* root = aRoot;
   do {
     const char* prefix = aPrefixFunc ? aPrefixFunc(aGetTreePrefixData, root) : "";
     printf("%s", NS_ConvertUTF16toUTF8(level).get());
     logging::AccessibleInfo(prefix, root);
     if (root->FirstChild() && !root->FirstChild()->IsDoc()) {
       level.Append(NS_LITERAL_STRING("  "));
       root = root->FirstChild();
       continue;
     }
-    int32_t idxInParent = !root->IsDoc() && root->mParent ?
+    int32_t idxInParent = root != aRoot && root->mParent ?
       root->mParent->mChildren.IndexOf(root) : -1;
     if (idxInParent != -1 &&
         idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
       root = root->mParent->mChildren.ElementAt(idxInParent + 1);
       continue;
     }
-    while (!root->IsDoc() && (root = root->Parent())) {
+    while (root != aRoot && (root = root->Parent())) {
       level.Cut(0, 2);
       int32_t idxInParent = !root->IsDoc() && root->mParent ?
         root->mParent->mChildren.IndexOf(root) : -1;
       if (idxInParent != -1 &&
           idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
         root = root->mParent->mChildren.ElementAt(idxInParent + 1);
         break;
       }
     }
   }
-  while (root && !root->IsDoc());
+  while (root && root != aRoot);
 
   logging::MsgEnd();
 }
 
 void
 logging::DOMTree(const char* aTitle, const char* aMsgText,
                  DocAccessible* aDocument)
 {
--- a/accessible/base/Logging.h
+++ b/accessible/base/Logging.h
@@ -138,17 +138,17 @@ void TreeInfo(const char* aMsg, uint32_t
               const char* aMsg1, Accessible* aAcc,
               const char* aMsg2, nsINode* aNode);
 void TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent);
 
 /**
  * Log the accessible/DOM tree.
  */
 typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
-void Tree(const char* aTitle, const char* aMsgText, DocAccessible* aDoc,
+void Tree(const char* aTitle, const char* aMsgText, Accessible* aRoot,
           GetTreePrefix aPrefixFunc = nullptr, void* aGetTreePrefixData = nullptr);
 void DOMTree(const char* aTitle, const char* aMsgText, DocAccessible* aDoc);
 
 /**
  * Log the message ('title: text' format) on new line. Print the start and end
  * boundaries of the message body designated by '{' and '}' (2 spaces indent for
  * body).
  */
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -415,16 +415,20 @@ NotificationController::WillRefresh(mozi
 
       ipcDoc = new DocAccessibleChild(childDoc);
       childDoc->SetIPCDoc(ipcDoc);
       nsCOMPtr<nsITabChild> tabChild =
         do_GetInterface(mDocument->DocumentNode()->GetDocShell());
       if (tabChild) {
         static_cast<TabChild*>(tabChild.get())->
           SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
+#if defined(XP_WIN)
+        IAccessibleHolder holder(CreateHolderFromAccessible(childDoc));
+        ipcDoc->SendCOMProxy(holder);
+#endif
       }
     }
   }
 
   mObservingState = eRefreshObserving;
   if (!mDocument)
     return;
 
--- a/accessible/base/Platform.h
+++ b/accessible/base/Platform.h
@@ -1,14 +1,17 @@
 /* -*- 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/. */
 
+#ifndef mozilla_a11y_Platform_h
+#define mozilla_a11y_Platform_h
+
 #include <stdint.h>
 
 class nsString;
 
 namespace mozilla {
 namespace a11y {
 
 class ProxyAccessible;
@@ -77,8 +80,9 @@ void ProxyTextChangeEvent(ProxyAccessibl
                           bool aFromUser);
 void ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
                         bool aInsert, bool aFromUser);
 void ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible* aWidget,
                          uint32_t aType);
 } // namespace a11y
 } // namespace mozilla
 
+#endif // mozilla_a11y_Platform_h
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -58,16 +58,28 @@ if CONFIG['A11Y_LOG']:
     UNIFIED_SOURCES += [
         'Logging.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/ipc',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/win',
+    ]
+else:
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/other',
+    ]
+
+LOCAL_INCLUDES += [
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
     '/dom/xbl',
     '/ipc/chromium/src',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -405,17 +405,17 @@ class PluginTimerCallBack final : public
 {
   ~PluginTimerCallBack() {}
 
 public:
   PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
 
   NS_DECL_ISUPPORTS
 
-  NS_IMETHODIMP Notify(nsITimer* aTimer) final
+  NS_IMETHOD Notify(nsITimer* aTimer) final
   {
     if (!mContent->IsInUncomposedDoc())
       return NS_OK;
 
     nsIPresShell* ps = mContent->OwnerDoc()->GetShell();
     if (ps) {
       DocAccessible* doc = ps->GetDocAccessible();
       if (doc) {
@@ -1285,16 +1285,18 @@ nsAccessibilityService::Init()
 #endif
 
   gIsShutdown = false;
 
   // Now its safe to start platform accessibility.
   if (XRE_IsParentProcess())
     PlatformInit();
 
+  statistics::A11yInitialized();
+
   return true;
 }
 
 void
 nsAccessibilityService::Shutdown()
 {
   // Application is going to be closed, shutdown accessibility and mark
   // accessibility service as shutdown to prevent calls of its methods.
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -520,18 +520,17 @@ Accessible::ChildAtPoint(int32_t aX, int
   NS_ENSURE_TRUE(rootFrame, nullptr);
 
   nsIFrame* startFrame = rootFrame;
 
   // Check whether the point is at popup content.
   nsIWidget* rootWidget = rootFrame->GetView()->GetNearestWidget(nullptr);
   NS_ENSURE_TRUE(rootWidget, nullptr);
 
-  LayoutDeviceIntRect rootRect;
-  rootWidget->GetScreenBounds(rootRect);
+  LayoutDeviceIntRect rootRect = rootWidget->GetScreenBounds();
 
   WidgetMouseEvent dummyEvent(true, eMouseMove, rootWidget,
                               WidgetMouseEvent::eSynthesized);
   dummyEvent.mRefPoint = LayoutDeviceIntPoint(aX - rootRect.x, aY - rootRect.y);
 
   nsIFrame* popupFrame = nsLayoutUtils::
     GetPopupFrameForEventCoordinates(accDocument->PresContext()->GetRootPresContext(),
                                      &dummyEvent);
@@ -850,47 +849,47 @@ Accessible::HandleAccEvent(AccEvent* aEv
 
         case nsIAccessibleEvent::EVENT_REORDER:
           // reorder events on the application acc aren't necessary to tell the parent
           // about new top level documents.
           if (!aEvent->GetAccessible()->IsApplication())
             ipcDoc->SendEvent(id, aEvent->GetEventType());
           break;
         case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
-                                                       AccStateChangeEvent* event = downcast_accEvent(aEvent);
-                                                       ipcDoc->SendStateChangeEvent(id, event->GetState(),
-                                                                                    event->IsStateEnabled());
-                                                       break;
-                                                     }
+          AccStateChangeEvent* event = downcast_accEvent(aEvent);
+          ipcDoc->SendStateChangeEvent(id, event->GetState(),
+                                       event->IsStateEnabled());
+          break;
+        }
         case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
           AccCaretMoveEvent* event = downcast_accEvent(aEvent);
           ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset());
           break;
         }
         case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
         case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
           AccTextChangeEvent* event = downcast_accEvent(aEvent);
           ipcDoc->SendTextChangeEvent(id, event->ModifiedText(),
                                       event->GetStartOffset(),
                                       event->GetLength(),
                                       event->IsTextInserted(),
                                       event->IsFromUserInput());
           break;
-                                                     }
+        }
         case nsIAccessibleEvent::EVENT_SELECTION:
         case nsIAccessibleEvent::EVENT_SELECTION_ADD:
         case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
           AccSelChangeEvent* selEvent = downcast_accEvent(aEvent);
           uint64_t widgetID = selEvent->Widget()->IsDoc() ? 0 :
             reinterpret_cast<uintptr_t>(selEvent->Widget());
           ipcDoc->SendSelectionEvent(id, widgetID, aEvent->GetEventType());
           break;
-                                                         }
+        }
         default:
-                                                         ipcDoc->SendEvent(id, aEvent->GetEventType());
+          ipcDoc->SendEvent(id, aEvent->GetEventType());
       }
     }
   }
 
   if (nsCoreUtils::AccEventObserversExist()) {
     nsCoreUtils::DispatchAccEvent(MakeXPCEvent(aEvent));
   }
 
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -9,16 +9,17 @@
 #include "mozilla/a11y/AccTypes.h"
 #include "mozilla/a11y/RelationType.h"
 #include "mozilla/a11y/Role.h"
 #include "mozilla/a11y/States.h"
 
 #include "mozilla/UniquePtr.h"
 
 #include "nsIContent.h"
+#include "nsIContentInlines.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 #include "nsRect.h"
 
 struct nsRoleMapEntry;
 
 struct nsRect;
@@ -49,17 +50,17 @@ class TableAccessible;
 class TableCellAccessible;
 class TextLeafAccessible;
 class XULLabelAccessible;
 class XULTreeAccessible;
 
 #ifdef A11Y_LOG
 namespace logging {
   typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
-  void Tree(const char* aTitle, const char* aMsgText, DocAccessible* aDoc,
+  void Tree(const char* aTitle, const char* aMsgText, Accessible* aRoot,
             GetTreePrefix aPrefixFunc, void* GetTreePrefixData);
 };
 #endif
 
 /**
  * Name type flags.
  */
 enum ENameValueFlag {
@@ -1131,17 +1132,17 @@ protected:
   uint32_t mContextFlags : kContextFlagsBits;
   uint32_t mType : kTypeBits;
   uint32_t mGenericTypes : kGenericTypesBits;
 
   void StaticAsserts() const;
 
 #ifdef A11Y_LOG
   friend void logging::Tree(const char* aTitle, const char* aMsgText,
-                            DocAccessible* aDoc,
+                            Accessible* aRoot,
                             logging::GetTreePrefix aPrefixFunc,
                             void* aGetTreePrefixData);
 #endif
   friend class DocAccessible;
   friend class xpcAccessible;
   friend class TreeMutation;
 
   UniquePtr<mozilla::a11y::EmbeddedObjCollector> mEmbeddedObjCollector;
--- a/accessible/generic/DocAccessible-inl.h
+++ b/accessible/generic/DocAccessible-inl.h
@@ -152,16 +152,22 @@ DocAccessible::CreateSubtree(Accessible*
 {
   // If a focused node has been shown then it could mean its frame was recreated
   // while the node stays focused and we need to fire focus event on
   // the accessible we just created. If the queue contains a focus event for
   // this node already then it will be suppressed by this one.
   Accessible* focusedAcc = nullptr;
   CacheChildrenInSubtree(aChild, &focusedAcc);
 
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eVerbose)) {
+    logging::Tree("TREE", "Created subtree", aChild);
+  }
+#endif
+
   // Fire events for ARIA elements.
   if (aChild->HasARIARole()) {
     roles::Role role = aChild->ARIARole();
     if (role == roles::MENUPOPUP) {
       FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
     }
     else if (role == roles::ALERT) {
       FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -759,20 +759,18 @@ DocAccessible::AttributeChanged(nsIDocum
   Accessible* accessible = GetAccessible(aElement);
   if (!accessible) {
     if (mContent != aElement)
       return;
 
     accessible = this;
   }
 
-  if (!accessible->IsBoundToParent()) {
-    MOZ_ASSERT_UNREACHABLE("DOM attribute change on accessible detached from tree");
-    return;
-  }
+  MOZ_ASSERT(accessible->IsBoundToParent() || accessible->IsDoc(),
+             "DOM attribute change on an accessible detached from the tree");
 
   // Fire accessible events iff there's an accessible, otherwise we consider
   // the accessible state wasn't changed, i.e. its state is initial state.
   AttributeChangedImpl(accessible, aNameSpaceID, aAttribute);
 
   // Update dependent IDs cache. Take care of accessible elements because no
   // accessible element means either the element is not accessible at all or
   // its accessible will be created later. It doesn't make sense to keep
@@ -975,17 +973,17 @@ DocAccessible::ARIAAttributeChanged(Acce
   nsIContent* elm = aAccessible->GetContent();
 
   // Update aria-hidden flag for the whole subtree iff aria-hidden is changed
   // on the root, i.e. ignore any affiliated aria-hidden changes in the subtree
   // of top aria-hidden.
   if (aAttribute == nsGkAtoms::aria_hidden) {
     bool isDefined = aria::HasDefinedARIAHidden(elm);
     if (isDefined != aAccessible->IsARIAHidden() &&
-        !aAccessible->Parent()->IsARIAHidden()) {
+        (!aAccessible->Parent() || !aAccessible->Parent()->IsARIAHidden())) {
       aAccessible->SetARIAHidden(isDefined);
 
       RefPtr<AccEvent> event =
         new AccObjectAttrChangedEvent(aAccessible, aAttribute);
       FireDelayedEvent(event);
     }
     return;
   }
@@ -1447,16 +1445,21 @@ DocAccessible::DoInitialUpdate()
 
   mLoadState |= eTreeConstructed;
 
   // Set up a root element and ARIA role mapping.
   UpdateRootElIfNeeded();
 
   // Build initial tree.
   CacheChildrenInSubtree(this);
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eVerbose)) {
+    logging::Tree("TREE", "Initial subtree", this);
+  }
+#endif
 
   // Fire reorder event after the document tree is constructed. Note, since
   // this reorder event is processed by parent document then events targeted to
   // this document may be fired prior to this reorder event. If this is
   // a problem then consider to keep event processing per tab document.
   if (!IsRoot()) {
     RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
     ParentDocument()->FireDelayedEvent(reorderEvent);
@@ -1758,17 +1761,17 @@ InsertIterator::Next()
     }
 
 #ifdef A11Y_LOG
     logging::TreeInfo("traversing an inserted node", logging::eVerbose,
                       "container", container, "node", node);
 #endif
 
     // If inserted nodes are siblings then just move the walker next.
-    if (prevNode && prevNode->GetNextSibling() == node) {
+    if (mChild && prevNode && prevNode->GetNextSibling() == node) {
       Accessible* nextChild = mWalker.Scope(node);
       if (nextChild) {
         mChildBefore = mChild;
         mChild = nextChild;
         return true;
       }
     }
     else {
@@ -2207,19 +2210,16 @@ DocAccessible::CacheChildrenInSubtree(Ac
   // If the accessible is focused then report a focus event after all related
   // mutation events.
   if (aFocusedAcc && !*aFocusedAcc &&
       FocusMgr()->HasDOMFocus(aRoot->GetContent()))
     *aFocusedAcc = aRoot;
 
   Accessible* root = aRoot->IsHTMLCombobox() ? aRoot->FirstChild() : aRoot;
   if (root->KidsFromDOM()) {
-#ifdef A11Y_LOG
-  logging::TreeInfo("caching children", logging::eVerbose, aRoot);
-#endif
     TreeMutation mt(root, TreeMutation::kNoEvents);
     TreeWalker walker(root);
     while (Accessible* child = walker.Next()) {
       if (child->IsBoundToParent()) {
         MoveChild(child, root, root->ChildCount());
         continue;
       }
 
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -572,17 +572,17 @@ protected:
   bool IsLoadEventTarget() const;
 
   /*
    * Set the object responsible for communicating with the main process on
    * behalf of this document.
    */
   void SetIPCDoc(DocAccessibleChild* aIPCDoc) { mIPCDoc = aIPCDoc; }
 
-  friend class DocAccessibleChild;
+  friend class DocAccessibleChildBase;
 
   /**
    * Used to fire scrolling end event after page scroll.
    *
    * @param aTimer    [in] the timer object
    * @param aClosure  [in] the document accessible where scrolling happens
    */
   static void ScrollTimerCallback(nsITimer* aTimer, void* aClosure);
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -439,27 +439,27 @@ HyperTextAccessible::OffsetToDOMPoint(in
 DOMPoint
 HyperTextAccessible::ClosestNotGeneratedDOMPoint(const DOMPoint& aDOMPoint,
                                                  nsIContent* aElementContent)
 {
   MOZ_ASSERT(aDOMPoint.node, "The node must not be null");
 
   // ::before pseudo element
   if (aElementContent &&
-      aElementContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) {
+      aElementContent->IsGeneratedContentContainerForBefore()) {
     MOZ_ASSERT(aElementContent->GetParent(),
                "::before must have parent element");
     // The first child of its parent (i.e., immediately after the ::before) is
     // good point for a DOM range.
     return DOMPoint(aElementContent->GetParent(), 0);
   }
 
   // ::after pseudo element
   if (aElementContent &&
-      aElementContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) {
+      aElementContent->IsGeneratedContentContainerForAfter()) {
     MOZ_ASSERT(aElementContent->GetParent(),
                "::after must have parent element");
     // The end of its parent (i.e., immediately before the ::after) is good
     // point for a DOM range.
     return DOMPoint(aElementContent->GetParent(),
                     aElementContent->GetParent()->GetChildCount());
   }
 
--- a/accessible/generic/OuterDocAccessible.cpp
+++ b/accessible/generic/OuterDocAccessible.cpp
@@ -168,16 +168,50 @@ OuterDocAccessible::RemoveChild(Accessib
 bool
 OuterDocAccessible::IsAcceptableChild(nsIContent* aEl) const
 {
   // outer document accessible doesn't not participate in ordinal tree
   // mutations.
   return false;
 }
 
+#if defined(XP_WIN)
+
+// On Windows e10s, since we don't cache in the chrome process, these next two
+// functions must be implemented so that we properly cross the chrome-to-content
+// boundary when traversing.
+
+uint32_t
+OuterDocAccessible::ChildCount() const
+{
+  uint32_t result = mChildren.Length();
+  if (!result && RemoteChildDoc()) {
+    result = 1;
+  }
+  return result;
+}
+
+Accessible*
+OuterDocAccessible::GetChildAt(uint32_t aIndex) const
+{
+  Accessible* result = AccessibleWrap::GetChildAt(aIndex);
+  if (result || aIndex) {
+    return result;
+  }
+  // If we are asking for child 0 and GetChildAt doesn't return anything, try
+  // to get the remote child doc and return that instead.
+  ProxyAccessible* remoteChild = RemoteChildDoc();
+  if (!remoteChild) {
+    return nullptr;
+  }
+  return WrapperFor(remoteChild);
+}
+
+#endif // defined(XP_WIN)
+
 ProxyAccessible*
 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
@@ -35,22 +35,27 @@ public:
   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;
   virtual bool RemoveChild(Accessible* aAccessible) override;
   virtual bool IsAcceptableChild(nsIContent* aEl) const override;
 
+#if defined(XP_WIN)
+  virtual uint32_t ChildCount() const override;
+  virtual Accessible* GetChildAt(uint32_t aIndex) const override;
+#endif // defined(XP_WIN)
+
 protected:
   virtual ~OuterDocAccessible() override;
 };
 
 inline OuterDocAccessible*
 Accessible::AsOuterDoc()
 {
   return IsOuterDoc() ? static_cast<OuterDocAccessible*>(this) : nullptr;
 }
 
 } // namespace a11y
 } // namespace mozilla
 
-#endif  
+#endif
--- a/accessible/generic/moz.build
+++ b/accessible/generic/moz.build
@@ -23,24 +23,32 @@ UNIFIED_SOURCES += [
     'RootAccessible.cpp',
     'TableCellAccessible.cpp',
     'TextLeafAccessible.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/html',
-    '/accessible/ipc',
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
     '/layout/generic',
     '/layout/xul',
 ]
 
+if CONFIG['OS_ARCH'] == 'WINNT':
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/win',
+    ]
+else:
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/other',
+    ]
+
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     LOCAL_INCLUDES += [
         '/accessible/atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/DocAccessibleChildBase.cpp
@@ -0,0 +1,99 @@
+/* -*- 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 "mozilla/a11y/DocAccessibleChildBase.h"
+#include "mozilla/a11y/ProxyAccessible.h"
+
+#include "Accessible-inl.h"
+
+namespace mozilla {
+namespace a11y {
+
+/* static */ uint32_t
+DocAccessibleChildBase::InterfacesFor(Accessible* aAcc)
+{
+  uint32_t interfaces = 0;
+  if (aAcc->IsHyperText() && aAcc->AsHyperText()->IsTextRole())
+    interfaces |= Interfaces::HYPERTEXT;
+
+  if (aAcc->IsLink())
+    interfaces |= Interfaces::HYPERLINK;
+
+  if (aAcc->HasNumericValue())
+    interfaces |= Interfaces::VALUE;
+
+  if (aAcc->IsImage())
+    interfaces |= Interfaces::IMAGE;
+
+  if (aAcc->IsTable()) {
+    interfaces |= Interfaces::TABLE;
+  }
+
+  if (aAcc->IsTableCell())
+    interfaces |= Interfaces::TABLECELL;
+
+  if (aAcc->IsDoc())
+    interfaces |= Interfaces::DOCUMENT;
+
+  if (aAcc->IsSelect()) {
+    interfaces |= Interfaces::SELECTION;
+  }
+
+  if (aAcc->ActionCount()) {
+    interfaces |= Interfaces::ACTION;
+  }
+
+  return interfaces;
+}
+
+/* static */ void
+DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
+                                      nsTArray<AccessibleData>& aTree)
+{
+  uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
+  uint32_t role = aRoot->Role();
+  uint32_t childCount = aRoot->ChildCount();
+  uint32_t interfaces = InterfacesFor(aRoot);
+
+#if defined(XP_WIN)
+  IAccessibleHolder holder(CreateHolderFromAccessible(aRoot));
+#endif
+
+  // OuterDocAccessibles are special because we don't want to serialize the
+  // child doc here, we'll call PDocAccessibleConstructor in
+  // NotificationController.
+  MOZ_ASSERT(!aRoot->IsDoc(), "documents shouldn't be serialized");
+  if (aRoot->IsOuterDoc()) {
+    childCount = 0;
+  }
+
+#if defined(XP_WIN)
+  aTree.AppendElement(AccessibleData(id, role, childCount, interfaces,
+                                     holder));
+#else
+  aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
+#endif
+
+  for (uint32_t i = 0; i < childCount; i++) {
+    SerializeTree(aRoot->GetChildAt(i), aTree);
+  }
+}
+
+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->InsertionIndex();
+  nsTArray<AccessibleData> shownTree;
+  ShowEventData data(parentID, idxInParent, shownTree);
+  SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
+  SendShowEvent(data, aShowEvent->IsFromUserInput());
+}
+
+} // namespace a11y
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/DocAccessibleChildBase.h
@@ -0,0 +1,70 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_DocAccessibleChildBase_h
+#define mozilla_a11y_DocAccessibleChildBase_h
+
+#include "mozilla/a11y/DocAccessible.h"
+#include "mozilla/a11y/PDocAccessibleChild.h"
+#include "nsISupportsImpl.h"
+
+namespace mozilla {
+namespace a11y {
+
+class Accessible;
+class AccShowEvent;
+
+class DocAccessibleChildBase : public PDocAccessibleChild
+{
+public:
+  explicit DocAccessibleChildBase(DocAccessible* aDoc)
+    : mDoc(aDoc)
+  {
+    MOZ_COUNT_CTOR(DocAccessibleChildBase);
+  }
+
+  ~DocAccessibleChildBase()
+  {
+    // Shutdown() should have been called, but maybe it isn't if the process is
+    // killed?
+    MOZ_ASSERT(!mDoc);
+    if (mDoc) {
+      mDoc->SetIPCDoc(nullptr);
+    }
+
+    MOZ_COUNT_DTOR(DocAccessibleChildBase);
+  }
+
+  void Shutdown()
+  {
+    mDoc->SetIPCDoc(nullptr);
+    mDoc = nullptr;
+    SendShutdown();
+  }
+
+  void ShowEvent(AccShowEvent* aShowEvent);
+
+  virtual void ActorDestroy(ActorDestroyReason) override
+  {
+    if (!mDoc) {
+      return;
+    }
+
+    mDoc->SetIPCDoc(nullptr);
+    mDoc = nullptr;
+  }
+
+protected:
+  static uint32_t InterfacesFor(Accessible* aAcc);
+  static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree);
+
+  DocAccessible*  mDoc;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_DocAccessibleChildBase_h
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -1,17 +1,16 @@
 /* -*- 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 "DocAccessibleParent.h"
 #include "mozilla/a11y/Platform.h"
-#include "ProxyAccessible.h"
 #include "mozilla/dom/TabParent.h"
 #include "xpcAccessibleDocument.h"
 #include "xpcAccEvents.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 
 namespace mozilla {
 namespace a11y {
@@ -98,19 +97,34 @@ DocAccessibleParent::AddSubtree(ProxyAcc
   }
 
   if (mAccessibles.Contains(newChild.ID())) {
     NS_ERROR("ID already in use");
     return 0;
   }
 
   auto role = static_cast<a11y::role>(newChild.Role());
+
+#if defined(XP_WIN)
+  const IAccessibleHolder& proxyStream = newChild.COMProxy();
+  RefPtr<IAccessible> comPtr(proxyStream.Get());
+  if (!comPtr) {
+    NS_ERROR("Could not obtain remote IAccessible interface");
+    return 0;
+  }
+
+  ProxyAccessible* newProxy =
+    new ProxyAccessible(newChild.ID(), aParent, this, role,
+                        newChild.Interfaces(), comPtr);
+#else
   ProxyAccessible* newProxy =
     new ProxyAccessible(newChild.ID(), aParent, this, role,
                         newChild.Interfaces());
+#endif
+
   aParent->AddChildAt(aIdxInParent, newProxy);
   mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
   ProxyCreated(newProxy, newChild.Interfaces());
 
   uint32_t accessibles = 1;
   uint32_t kids = newChild.ChildrenCount();
   for (uint32_t i = 0; i < kids; i++) {
     uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
@@ -447,10 +461,36 @@ DocAccessibleParent::CheckDocTree() cons
 xpcAccessibleGeneric*
 DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
 {
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   MOZ_ASSERT(doc);
 
   return doc->GetXPCAccessible(aProxy);
 }
+
+#if defined(XP_WIN)
+/**
+ * @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.
+ */
+bool
+DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
+                                  IAccessibleHolder* aParentCOMProxy)
+{
+  RefPtr<IAccessible> ptr(aCOMProxy.Get());
+  SetCOMInterface(ptr);
+
+  Accessible* outerDoc = OuterDocOfRemoteBrowser();
+  IAccessible* rawNative = nullptr;
+  if (outerDoc) {
+    outerDoc->GetNativeInterface((void**) &rawNative);
+  }
+
+  aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
+  return true;
+}
+#endif // defined(XP_WIN)
+
 } // a11y
 } // mozilla
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -3,18 +3,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/. */
 
 #ifndef mozilla_a11y_DocAccessibleParent_h
 #define mozilla_a11y_DocAccessibleParent_h
 
 #include "nsAccessibilityService.h"
-#include "ProxyAccessible.h"
 #include "mozilla/a11y/PDocAccessibleParent.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace a11y {
 
 class xpcAccessibleGeneric;
@@ -137,16 +137,21 @@ public:
 
   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]; }
 
+#if defined(XP_WIN)
+  virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
+                            IAccessibleHolder* aParentCOMProxy) override;
+#endif
+
 private:
 
   class ProxyEntry : public PLDHashEntryHdr
   {
   public:
     explicit ProxyEntry(const void*) : mProxy(nullptr) {}
     ProxyEntry(ProxyEntry&& aOther) :
       mProxy(aOther.mProxy) { aOther.mProxy = nullptr; }
rename from accessible/ipc/ProxyAccessible.cpp
rename to accessible/ipc/ProxyAccessibleBase.cpp
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessibleBase.cpp
@@ -1,74 +1,78 @@
 /* -*- 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 "ProxyAccessible.h"
-#include "DocAccessibleParent.h"
 #include "DocAccessible.h"
+#include "mozilla/a11y/DocAccessibleParent.h"
 #include "mozilla/a11y/DocManager.h"
+#include "mozilla/a11y/Platform.h"
+#include "mozilla/a11y/ProxyAccessibleBase.h"
+#include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/a11y/Role.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/unused.h"
-#include "mozilla/a11y/Platform.h"
 #include "RelationType.h"
-#include "mozilla/a11y/Role.h"
 #include "xpcAccessibleDocument.h"
 
 namespace mozilla {
 namespace a11y {
 
+template <class Derived>
 void
-ProxyAccessible::Shutdown()
+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(this);
+    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.
   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();
   }
 
   mChildren.Clear();
-  ProxyDestroyed(this);
-  mDoc->RemoveAccessible(this);
+  ProxyDestroyed(static_cast<Derived*>(this));
+  mDoc->RemoveAccessible(static_cast<Derived*>(this));
 }
 
+template <class Derived>
 void
-ProxyAccessible::SetChildDoc(DocAccessibleParent* aParent)
+ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aParent)
 {
   if (aParent) {
     MOZ_ASSERT(mChildren.IsEmpty());
     mChildren.AppendElement(aParent);
     mOuterDoc = true;
   } else {
     MOZ_ASSERT(mChildren.Length() == 1);
     mChildren.Clear();
     mOuterDoc = false;
   }
 }
 
+template <class Derived>
 bool
-ProxyAccessible::MustPruneChildren() const
+ProxyAccessibleBase<Derived>::MustPruneChildren() const
 {
   // this is the equivalent to nsAccUtils::MustPrune for proxies and should be
   // kept in sync with that.
   if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION
       && mRole != roles::OPTION && mRole != roles::ENTRY
       && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT
       && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON
       && mRole != roles::GRAPHIC && mRole != roles::SLIDER
@@ -77,998 +81,51 @@ ProxyAccessible::MustPruneChildren() con
 
   if (mChildren.Length() != 1)
     return false;
 
   return mChildren[0]->Role() == roles::TEXT_LEAF
     || mChildren[0]->Role() == roles::STATICTEXT;
 }
 
-uint64_t
-ProxyAccessible::State() const
-{
-  uint64_t state = 0;
-  Unused << mDoc->SendState(mID, &state);
-  return state;
-}
-
-uint64_t
-ProxyAccessible::NativeState() const
-{
-  uint64_t state = 0;
-  Unused << mDoc->SendNativeState(mID, &state);
-  return state;
-}
-
-void
-ProxyAccessible::Name(nsString& aName) const
-{
-  Unused << mDoc->SendName(mID, &aName);
-}
-
-void
-ProxyAccessible::Value(nsString& aValue) const
-{
-  Unused << mDoc->SendValue(mID, &aValue);
-}
-
-void
-ProxyAccessible::Help(nsString& aHelp) const
-{
-  Unused << mDoc->SendHelp(mID, &aHelp);
-}
-
-void
-ProxyAccessible::Description(nsString& aDesc) const
-{
-  Unused << mDoc->SendDescription(mID, &aDesc);
-}
-
-void
-ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const
-{
-  Unused << mDoc->SendAttributes(mID, aAttrs);
-}
-
-nsTArray<ProxyAccessible*>
-ProxyAccessible::RelationByType(RelationType aType) const
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendRelationByType(mID, static_cast<uint32_t>(aType),
-                                     &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  nsTArray<ProxyAccessible*> targets(targetCount);
-  for (size_t i = 0; i < targetCount; i++)
-    if (ProxyAccessible* proxy = mDoc->GetAccessible(targetIDs[i]))
-      targets.AppendElement(proxy);
-
-  return Move(targets);
-}
-
-void
-ProxyAccessible::Relations(nsTArray<RelationType>* aTypes,
-                           nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets)
-  const
-{
-  nsTArray<RelationTargets> ipcRelations;
-  Unused << mDoc->SendRelations(mID, &ipcRelations);
-
-  size_t relationCount = ipcRelations.Length();
-  aTypes->SetCapacity(relationCount);
-  aTargetSets->SetCapacity(relationCount);
-  for (size_t i = 0; i < relationCount; i++) {
-    uint32_t type = ipcRelations[i].Type();
-    if (type > static_cast<uint32_t>(RelationType::LAST))
-      continue;
-
-    size_t targetCount = ipcRelations[i].Targets().Length();
-    nsTArray<ProxyAccessible*> targets(targetCount);
-    for (size_t j = 0; j < targetCount; j++)
-      if (ProxyAccessible* proxy = mDoc->GetAccessible(ipcRelations[i].Targets()[j]))
-        targets.AppendElement(proxy);
-
-    if (targets.IsEmpty())
-      continue;
-
-    aTargetSets->AppendElement(Move(targets));
-    aTypes->AppendElement(static_cast<RelationType>(type));
-  }
-}
-
-bool
-ProxyAccessible::IsSearchbox() const
-{
-  bool retVal = false;
-  Unused << mDoc->SendIsSearchbox(mID, &retVal);
-  return retVal;
-}
-
-nsIAtom*
-ProxyAccessible::LandmarkRole() const
-{
-  nsString landmark;
-  Unused << mDoc->SendLandmarkRole(mID, &landmark);
-  return NS_GetStaticAtom(landmark);
-}
-
-nsIAtom*
-ProxyAccessible::ARIARoleAtom() const
-{
-  nsString role;
-  Unused << mDoc->SendARIARoleAtom(mID, &role);
-  return NS_GetStaticAtom(role);
-}
-
-int32_t
-ProxyAccessible::GetLevelInternal()
-{
-  int32_t level = 0;
-  Unused << mDoc->SendGetLevelInternal(mID, &level);
-  return level;
-}
-
-void
-ProxyAccessible::ScrollTo(uint32_t aScrollType)
-{
-  Unused << mDoc->SendScrollTo(mID, aScrollType);
-}
-
-void
-ProxyAccessible::ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY)
-{
-  Unused << mDoc->SendScrollToPoint(mID, aScrollType, aX, aY);
-}
-
-int32_t
-ProxyAccessible::CaretLineNumber()
-{
-  int32_t line = -1;
-  Unused << mDoc->SendCaretOffset(mID, &line);
-  return line;
-}
-
-int32_t
-ProxyAccessible::CaretOffset()
-{
-  int32_t offset = 0;
-  Unused << mDoc->SendCaretOffset(mID, &offset);
-  return offset;
-}
-
-void
-ProxyAccessible::SetCaretOffset(int32_t aOffset)
-{
-  Unused << mDoc->SendSetCaretOffset(mID, aOffset);
-}
-
-int32_t
-ProxyAccessible::CharacterCount()
-{
-  int32_t count = 0;
-  Unused << mDoc->SendCharacterCount(mID, &count);
-  return count;
-}
-
-int32_t
-ProxyAccessible::SelectionCount()
-{
-  int32_t count = 0;
-  Unused << mDoc->SendSelectionCount(mID, &count);
-  return count;
-}
-
-bool
-ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
-                               nsString& aText) const
-{
-  bool valid;
-  Unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText, &valid);
-  return valid;
-}
-
-void
-ProxyAccessible::GetTextAfterOffset(int32_t aOffset,
-                                    AccessibleTextBoundary aBoundaryType,
-                                    nsString& aText, int32_t* aStartOffset,
-                                    int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextAfterOffset(mID, aOffset, aBoundaryType,
-                                         &aText, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::GetTextAtOffset(int32_t aOffset,
-                                 AccessibleTextBoundary aBoundaryType,
-                                 nsString& aText, int32_t* aStartOffset,
-                                 int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextAtOffset(mID, aOffset, aBoundaryType,
-                                      &aText, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::GetTextBeforeOffset(int32_t aOffset,
-                                     AccessibleTextBoundary aBoundaryType,
-                                     nsString& aText, int32_t* aStartOffset,
-                                     int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextBeforeOffset(mID, aOffset, aBoundaryType,
-                                          &aText, aStartOffset, aEndOffset);
-}
-
-char16_t
-ProxyAccessible::CharAt(int32_t aOffset)
-{
-  uint16_t retval = 0;
-  Unused << mDoc->SendCharAt(mID, aOffset, &retval);
-  return static_cast<char16_t>(retval);
-}
-
-void
-ProxyAccessible::TextAttributes(bool aIncludeDefAttrs,
-                                int32_t aOffset,
-                                nsTArray<Attribute>* aAttributes,
-                                int32_t* aStartOffset,
-                                int32_t* aEndOffset)
-{
-  Unused << mDoc->SendTextAttributes(mID, aIncludeDefAttrs, aOffset,
-                                     aAttributes, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::DefaultTextAttributes(nsTArray<Attribute>* aAttrs)
-{
-  Unused << mDoc->SendDefaultTextAttributes(mID, aAttrs);
-}
-
-nsIntRect
-ProxyAccessible::TextBounds(int32_t aStartOffset, int32_t aEndOffset,
-                            uint32_t aCoordType)
-{
-  nsIntRect rect;
-  Unused <<
-    mDoc->SendTextBounds(mID, aStartOffset, aEndOffset, aCoordType, &rect);
-  return rect;
-}
-
-nsIntRect
-ProxyAccessible::CharBounds(int32_t aOffset, uint32_t aCoordType)
-{
-  nsIntRect rect;
-  Unused <<
-    mDoc->SendCharBounds(mID, aOffset, aCoordType, &rect);
-  return rect;
-}
-
-int32_t
-ProxyAccessible::OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType)
-{
-  int32_t retVal = -1;
-  Unused << mDoc->SendOffsetAtPoint(mID, aX, aY, aCoordType, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::SelectionBoundsAt(int32_t aSelectionNum,
-                                   nsString& aData,
-                                   int32_t* aStartOffset,
-                                   int32_t* aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendSelectionBoundsAt(mID, aSelectionNum, &retVal, &aData,
-                                        aStartOffset, aEndOffset);
-  return retVal;
-}
-
-bool
-ProxyAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
-                                      int32_t aStartOffset,
-                                      int32_t aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendSetSelectionBoundsAt(mID, aSelectionNum, aStartOffset,
-                                           aEndOffset, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::AddToSelection(int32_t aStartOffset,
-                                int32_t aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendAddToSelection(mID, aStartOffset, aEndOffset, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::RemoveFromSelection(int32_t aSelectionNum)
-{
-  bool retVal = false;
-  Unused << mDoc->SendRemoveFromSelection(mID, aSelectionNum, &retVal);
-  return retVal;
-}
-
-void
-ProxyAccessible::ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset,
-                                   uint32_t aScrollType)
-{
-  Unused << mDoc->SendScrollSubstringTo(mID, aStartOffset, aEndOffset, aScrollType);
-}
-
-void
-ProxyAccessible::ScrollSubstringToPoint(int32_t aStartOffset,
-                                        int32_t aEndOffset,
-                                        uint32_t aCoordinateType,
-                                        int32_t aX, int32_t aY)
-{
-  Unused << mDoc->SendScrollSubstringToPoint(mID, aStartOffset, aEndOffset,
-                                             aCoordinateType, aX, aY);
-}
-
-void
-ProxyAccessible::Text(nsString* aText)
-{
-  Unused << mDoc->SendText(mID, aText);
-}
-
-void
-ProxyAccessible::ReplaceText(const nsString& aText)
-{
-  Unused << mDoc->SendReplaceText(mID, aText);
-}
-
-bool
-ProxyAccessible::InsertText(const nsString& aText, int32_t aPosition)
-{
-  bool valid;
-  Unused << mDoc->SendInsertText(mID, aText, aPosition, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::CopyText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendCopyText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::CutText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendCutText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::DeleteText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendDeleteText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::PasteText(int32_t aPosition)
-{
-  bool valid;
-  Unused << mDoc->SendPasteText(mID, aPosition, &valid);
-  return valid;
-}
-
-nsIntPoint
-ProxyAccessible::ImagePosition(uint32_t aCoordType)
-{
-  nsIntPoint retVal;
-  Unused << mDoc->SendImagePosition(mID, aCoordType, &retVal);
-  return retVal;
-}
-
-nsIntSize
-ProxyAccessible::ImageSize()
-{
-  nsIntSize retVal;
-  Unused << mDoc->SendImageSize(mID, &retVal);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::StartOffset(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendStartOffset(mID, &retVal, aOk);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::EndOffset(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendEndOffset(mID, &retVal, aOk);
-  return retVal;
-}
-
-bool
-ProxyAccessible::IsLinkValid()
-{
-  bool retVal = false;
-  Unused << mDoc->SendIsLinkValid(mID, &retVal);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::AnchorCount(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendAnchorCount(mID, &retVal, aOk);
-  return retVal;
-}
-
-void
-ProxyAccessible::AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk)
-{
-  Unused << mDoc->SendAnchorURIAt(mID, aIndex, &aURI, aOk);
-}
-
-ProxyAccessible*
-ProxyAccessible::AnchorAt(uint32_t aIndex)
-{
-  uint64_t id = 0;
-  bool ok = false;
-  Unused << mDoc->SendAnchorAt(mID, aIndex, &id, &ok);
-  return ok ? mDoc->GetAccessible(id) : nullptr;
-}
-
+template <class Derived>
 uint32_t
-ProxyAccessible::LinkCount()
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendLinkCount(mID, &retVal);
-  return retVal;
-}
-
-ProxyAccessible*
-ProxyAccessible::LinkAt(const uint32_t& aIndex)
-{
-  uint64_t linkID = 0;
-  bool ok = false;
-  Unused << mDoc->SendLinkAt(mID, aIndex, &linkID, &ok);
-  return ok ? mDoc->GetAccessible(linkID) : nullptr;
-}
-
-int32_t
-ProxyAccessible::LinkIndexOf(ProxyAccessible* aLink)
-{
-  int32_t retVal = -1;
-  if (aLink) {
-    Unused << mDoc->SendLinkIndexOf(mID, aLink->ID(), &retVal);
-  }
-
-  return retVal;
-}
-
-int32_t
-ProxyAccessible::LinkIndexAtOffset(uint32_t aOffset)
-{
-  int32_t retVal = -1;
-  Unused << mDoc->SendLinkIndexAtOffset(mID, aOffset, &retVal);
-  return retVal;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableOfACell()
-{
-  uint64_t tableID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableOfACell(mID, &tableID, &ok);
-  return ok ? mDoc->GetAccessible(tableID) : nullptr;
-}
-
-uint32_t
-ProxyAccessible::ColIdx()
-{
-  uint32_t index = 0;
-  Unused << mDoc->SendColIdx(mID, &index);
-  return index;
-}
-
-uint32_t
-ProxyAccessible::RowIdx()
-{
-  uint32_t index = 0;
-  Unused << mDoc->SendRowIdx(mID, &index);
-  return index;
-}
-
-uint32_t
-ProxyAccessible::ColExtent()
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendColExtent(mID, &extent);
-  return extent;
-}
-
-uint32_t
-ProxyAccessible::RowExtent()
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendRowExtent(mID, &extent);
-  return extent;
-}
-
-void
-ProxyAccessible::ColHeaderCells(nsTArray<ProxyAccessible*>* aCells)
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendColHeaderCells(mID, &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  for (size_t i = 0; i < targetCount; i++) {
-    aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
-  }
-}
-
-void
-ProxyAccessible::RowHeaderCells(nsTArray<ProxyAccessible*>* aCells)
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendRowHeaderCells(mID, &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  for (size_t i = 0; i < targetCount; i++) {
-    aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
-  }
-}
-
-bool
-ProxyAccessible::IsCellSelected()
-{
-  bool selected = false;
-  Unused << mDoc->SendIsCellSelected(mID, &selected);
-  return selected;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableCaption()
-{
-  uint64_t captionID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableCaption(mID, &captionID, &ok);
-  return ok ? mDoc->GetAccessible(captionID) : nullptr;
-}
-
-void
-ProxyAccessible::TableSummary(nsString& aSummary)
-{
-  Unused << mDoc->SendTableSummary(mID, &aSummary);
-}
-
-uint32_t
-ProxyAccessible::TableColumnCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableColumnCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableRowCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableRowCount(mID, &count);
-  return count;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableCellAt(uint32_t aRow, uint32_t aCol)
-{
-  uint64_t cellID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableCellAt(mID, aRow, aCol, &cellID, &ok);
-  return ok ? mDoc->GetAccessible(cellID) : nullptr;
-}
-
-int32_t
-ProxyAccessible::TableCellIndexAt(uint32_t aRow, uint32_t aCol)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableCellIndexAt(mID, aRow, aCol, &index);
-  return index;
-}
-
-int32_t
-ProxyAccessible::TableColumnIndexAt(uint32_t aCellIndex)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableColumnIndexAt(mID, aCellIndex, &index);
-  return index;
-}
-
-int32_t
-ProxyAccessible::TableRowIndexAt(uint32_t aCellIndex)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableRowIndexAt(mID, aCellIndex, &index);
-  return index;
-}
-
-void
-ProxyAccessible::TableRowAndColumnIndicesAt(uint32_t aCellIndex,
-                                            int32_t* aRow, int32_t* aCol)
-{
-  Unused << mDoc->SendTableRowAndColumnIndicesAt(mID, aCellIndex, aRow, aCol);
-}
-
-uint32_t
-ProxyAccessible::TableColumnExtentAt(uint32_t aRow, uint32_t aCol)
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendTableColumnExtentAt(mID, aRow, aCol, &extent);
-  return extent;
-}
-
-uint32_t
-ProxyAccessible::TableRowExtentAt(uint32_t aRow, uint32_t aCol)
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendTableRowExtentAt(mID, aRow, aCol, &extent);
-  return extent;
-}
-
-void
-ProxyAccessible::TableColumnDescription(uint32_t aCol, nsString& aDescription)
-{
-  Unused << mDoc->SendTableColumnDescription(mID, aCol, &aDescription);
-}
-
-void
-ProxyAccessible::TableRowDescription(uint32_t aRow, nsString& aDescription)
-{
-  Unused << mDoc->SendTableRowDescription(mID, aRow, &aDescription);
-}
-
-bool
-ProxyAccessible::TableColumnSelected(uint32_t aCol)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableColumnSelected(mID, aCol, &selected);
-  return selected;
-}
-
-bool
-ProxyAccessible::TableRowSelected(uint32_t aRow)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableRowSelected(mID, aRow, &selected);
-  return selected;
-}
-
-bool
-ProxyAccessible::TableCellSelected(uint32_t aRow, uint32_t aCol)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableCellSelected(mID, aRow, aCol, &selected);
-  return selected;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedCellCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedCellCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedColumnCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedColumnCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedRowCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedRowCount(mID, &count);
-  return count;
-}
-
-void
-ProxyAccessible::TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs)
-{
-  AutoTArray<uint64_t, 30> cellIDs;
-  Unused << mDoc->SendTableSelectedCells(mID, &cellIDs);
-  aCellIDs->SetCapacity(cellIDs.Length());
-  for (uint32_t i = 0; i < cellIDs.Length(); ++i) {
-    aCellIDs->AppendElement(mDoc->GetAccessible(cellIDs[i]));
-  }
-}
-
-void
-ProxyAccessible::TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices)
-{
-  Unused << mDoc->SendTableSelectedCellIndices(mID, aCellIndices);
-}
-
-void
-ProxyAccessible::TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices)
-{
-  Unused << mDoc->SendTableSelectedColumnIndices(mID, aColumnIndices);
-}
-
-void
-ProxyAccessible::TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices)
-{
-  Unused << mDoc->SendTableSelectedRowIndices(mID, aRowIndices);
-}
-
-void
-ProxyAccessible::TableSelectColumn(uint32_t aCol)
-{
-  Unused << mDoc->SendTableSelectColumn(mID, aCol);
-}
-
-void
-ProxyAccessible::TableSelectRow(uint32_t aRow)
-{
-  Unused << mDoc->SendTableSelectRow(mID, aRow);
-}
-
-void
-ProxyAccessible::TableUnselectColumn(uint32_t aCol)
-{
-  Unused << mDoc->SendTableUnselectColumn(mID, aCol);
-}
-
-void
-ProxyAccessible::TableUnselectRow(uint32_t aRow)
-{
-  Unused << mDoc->SendTableUnselectRow(mID, aRow);
-}
-
-bool
-ProxyAccessible::TableIsProbablyForLayout()
-{
-  bool forLayout = false;
-  Unused << mDoc->SendTableIsProbablyForLayout(mID, &forLayout);
-  return forLayout;
-}
-
-ProxyAccessible*
-ProxyAccessible::AtkTableColumnHeader(int32_t aCol)
-{
-  uint64_t headerID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAtkTableColumnHeader(mID, aCol, &headerID, &ok);
-  return ok ? mDoc->GetAccessible(headerID) : nullptr;
-}
-
-ProxyAccessible*
-ProxyAccessible::AtkTableRowHeader(int32_t aRow)
-{
-  uint64_t headerID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAtkTableRowHeader(mID, aRow, &headerID, &ok);
-  return ok ? mDoc->GetAccessible(headerID) : nullptr;
-}
-
-void
-ProxyAccessible::SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems)
-{
-  AutoTArray<uint64_t, 10> itemIDs;
-  Unused << mDoc->SendSelectedItems(mID, &itemIDs);
-  aSelectedItems->SetCapacity(itemIDs.Length());
-  for (size_t i = 0; i < itemIDs.Length(); ++i) {
-    aSelectedItems->AppendElement(mDoc->GetAccessible(itemIDs[i]));
-  }
-}
-
-uint32_t
-ProxyAccessible::SelectedItemCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendSelectedItemCount(mID, &count);
-  return count;
-}
-
-ProxyAccessible*
-ProxyAccessible::GetSelectedItem(uint32_t aIndex)
-{
-  uint64_t selectedItemID = 0;
-  bool ok = false;
-  Unused << mDoc->SendGetSelectedItem(mID, aIndex, &selectedItemID, &ok);
-  return ok ? mDoc->GetAccessible(selectedItemID) : nullptr;
-}
-
-bool
-ProxyAccessible::IsItemSelected(uint32_t aIndex)
-{
-  bool selected = false;
-  Unused << mDoc->SendIsItemSelected(mID, aIndex, &selected);
-  return selected;
-}
- 
-bool
-ProxyAccessible::AddItemToSelection(uint32_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendAddItemToSelection(mID, aIndex, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::RemoveItemFromSelection(uint32_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendRemoveItemFromSelection(mID, aIndex, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::SelectAll()
-{
-  bool success = false;
-  Unused << mDoc->SendSelectAll(mID, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::UnselectAll()
-{
-  bool success = false;
-  Unused << mDoc->SendUnselectAll(mID, &success);
-  return success;
-}
-
-void
-ProxyAccessible::TakeSelection()
-{
-  Unused << mDoc->SendTakeSelection(mID);
-}
-
-void
-ProxyAccessible::SetSelected(bool aSelect)
-{
-  Unused << mDoc->SendSetSelected(mID, aSelect);
-}
-
-bool
-ProxyAccessible::DoAction(uint8_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendDoAction(mID, aIndex, &success);
-  return success;
-}
-
-uint8_t
-ProxyAccessible::ActionCount()
-{
-  uint8_t count = 0;
-  Unused << mDoc->SendActionCount(mID, &count);
-  return count;
-}
-
-void
-ProxyAccessible::ActionDescriptionAt(uint8_t aIndex, nsString& aDescription)
-{
-  Unused << mDoc->SendActionDescriptionAt(mID, aIndex, &aDescription);
-}
-
-void
-ProxyAccessible::ActionNameAt(uint8_t aIndex, nsString& aName)
-{
-  Unused << mDoc->SendActionNameAt(mID, aIndex, &aName);
-}
-
-KeyBinding
-ProxyAccessible::AccessKey()
-{
-  uint32_t key = 0;
-  uint32_t modifierMask = 0;
-  Unused << mDoc->SendAccessKey(mID, &key, &modifierMask);
-  return KeyBinding(key, modifierMask);
-}
-
-KeyBinding
-ProxyAccessible::KeyboardShortcut()
-{
-  uint32_t key = 0;
-  uint32_t modifierMask = 0;
-  Unused << mDoc->SendKeyboardShortcut(mID, &key, &modifierMask);
-  return KeyBinding(key, modifierMask);
-}
-
-void
-ProxyAccessible::AtkKeyBinding(nsString& aBinding)
-{
-  Unused << mDoc->SendAtkKeyBinding(mID, &aBinding);
-}
-
-double
-ProxyAccessible::CurValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendCurValue(mID, &val);
-  return val;
-}
-
-bool
-ProxyAccessible::SetCurValue(double aValue)
-{
-  bool success = false;
-  Unused << mDoc->SendSetCurValue(mID, aValue, &success);
-  return success;
-}
-
-double
-ProxyAccessible::MinValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendMinValue(mID, &val);
-  return val;
-}
-
-double
-ProxyAccessible::MaxValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendMaxValue(mID, &val);
-  return val;
-}
-
-double
-ProxyAccessible::Step()
-{
-  double step = UnspecifiedNaN<double>();
-  Unused << mDoc->SendStep(mID, &step);
-  return step;
-}
-
-void
-ProxyAccessible::TakeFocus()
-{
-  Unused << mDoc->SendTakeFocus(mID);
-}
-
-uint32_t
-ProxyAccessible::EmbeddedChildCount() const
+ProxyAccessibleBase<Derived>::EmbeddedChildCount() const
 {
   size_t count = 0, kids = mChildren.Length();
   for (size_t i = 0; i < kids; i++) {
     if (mChildren[i]->IsEmbeddedObject()) {
       count++;
     }
   }
 
   return count;
 }
 
+template <class Derived>
 int32_t
-ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
+ProxyAccessibleBase<Derived>::IndexOfEmbeddedChild(const Derived* aChild)
 {
   size_t index = 0, kids = mChildren.Length();
   for (size_t i = 0; i < kids; i++) {
     if (mChildren[i]->IsEmbeddedObject()) {
       if (mChildren[i] == aChild) {
         return index;
       }
 
       index++;
     }
   }
 
   return -1;
 }
 
-ProxyAccessible*
-ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
+template <class Derived>
+Derived*
+ProxyAccessibleBase<Derived>::EmbeddedChildAt(size_t aChildIdx)
 {
   size_t index = 0, kids = mChildren.Length();
   for (size_t i = 0; i < kids; i++) {
     if (!mChildren[i]->IsEmbeddedObject()) {
       continue;
     }
 
     if (index == aChildIdx) {
@@ -1076,117 +133,27 @@ ProxyAccessible::EmbeddedChildAt(size_t 
     }
 
     index++;
   }
 
   return nullptr;
 }
 
-ProxyAccessible*
-ProxyAccessible::FocusedChild()
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused << mDoc->SendFocusedChild(mID, &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
-}
-
-ProxyAccessible*
-ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
-                              Accessible::EWhichChildAtPoint aWhichChild)
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAccessibleAtPoint(mID, aX, aY, false,
-                                        static_cast<uint32_t>(aWhichChild),
-                                        &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
-}
-
-nsIntRect
-ProxyAccessible::Bounds()
-{
-  nsIntRect rect;
-  Unused << mDoc->SendExtents(mID, false,
-                              &(rect.x), &(rect.y),
-                              &(rect.width), &(rect.height));
-  return rect;
-}
-
-void
-ProxyAccessible::Language(nsString& aLocale)
-{
-  Unused << mDoc->SendLanguage(mID, &aLocale);
-}
-
-void
-ProxyAccessible::DocType(nsString& aType)
-{
-  Unused << mDoc->SendDocType(mID, &aType);
-}
-
-void
-ProxyAccessible::Title(nsString& aTitle)
-{
-  Unused << mDoc->SendTitle(mID, &aTitle);
-}
-
-void
-ProxyAccessible::URL(nsString& aURL)
-{
-  Unused << mDoc->SendURL(mID, &aURL);
-}
-
-void
-ProxyAccessible::MimeType(nsString aMime)
-{
-  Unused << mDoc->SendMimeType(mID, &aMime);
-}
-
-void
-ProxyAccessible::URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
-                                    nsString& aMimeType)
-{
-  Unused << mDoc->SendURLDocTypeMimeType(mID, &aURL, &aDocType, &aMimeType);
-}
-
-ProxyAccessible*
-ProxyAccessible::AccessibleAtPoint(int32_t aX, int32_t aY,
-                                   bool aNeedsScreenCoords)
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused <<
-    mDoc->SendAccessibleAtPoint(mID, aX, aY, aNeedsScreenCoords,
-                                static_cast<uint32_t>(Accessible::eDirectChild),
-                                &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
-}
-
-void
-ProxyAccessible::Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY,
-                        int32_t* aWidth, int32_t* aHeight)
-{
-  Unused << mDoc->SendExtents(mID, aNeedsScreenCoords, aX, aY, aWidth, aHeight);
-}
-
-void
-ProxyAccessible::DOMNodeID(nsString& aID)
-{
-  Unused << mDoc->SendDOMNodeID(mID, &aID);
-}
-
+template <class Derived>
 Accessible*
-ProxyAccessible::OuterDocOfRemoteBrowser() const
+ProxyAccessibleBase<Derived>::OuterDocOfRemoteBrowser() const
 {
   auto tab = static_cast<dom::TabParent*>(mDoc->Manager());
   dom::Element* frame = tab->GetOwnerElement();
   NS_ASSERTION(frame, "why isn't the tab in a frame!");
   if (!frame)
     return nullptr;
 
   DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
 
   return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
 }
-}
-}
+
+template class ProxyAccessibleBase<ProxyAccessible>;
+
+} // namespace a11y
+} // namespace mozilla
rename from accessible/ipc/ProxyAccessible.h
rename to accessible/ipc/ProxyAccessibleBase.h
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessibleBase.h
@@ -1,109 +1,100 @@
 /* -*- 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/. */
 
-#ifndef mozilla_a11y_ProxyAccessible_h
-#define mozilla_a11y_ProxyAccessible_h
+#ifndef mozilla_a11y_ProxyAccessibleBase_h
+#define mozilla_a11y_ProxyAccessibleBase_h
 
 #include "mozilla/a11y/Role.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleTypes.h"
 #include "Accessible.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRect.h"
 #include "Accessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 class Accessible;
 class Attribute;
 class DocAccessibleParent;
+class ProxyAccessible;
 enum class RelationType;
 
 enum Interfaces
 {
   HYPERTEXT = 1,
   HYPERLINK = 1 << 1,
   IMAGE = 1 << 2,
   VALUE = 1 << 3,
   TABLE = 1 << 4,
   TABLECELL = 1 << 5,
   DOCUMENT = 1 << 6,
   SELECTION = 1 << 7,
   ACTION = 1 << 8,
 };
 
-class ProxyAccessible
+template <class Derived>
+class ProxyAccessibleBase
 {
 public:
-
-  ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
-                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) :
-     mParent(aParent), mDoc(aDoc), mWrapper(0), mID(aID), mRole(aRole),
-     mOuterDoc(false), mIsDoc(false),
-     mHasValue(aInterfaces & Interfaces::VALUE),
-     mIsHyperLink(aInterfaces & Interfaces::HYPERLINK),
-     mIsHyperText(aInterfaces & Interfaces::HYPERTEXT)
+  ~ProxyAccessibleBase()
   {
-    MOZ_COUNT_CTOR(ProxyAccessible);
-  }
-  ~ProxyAccessible()
-  {
-    MOZ_COUNT_DTOR(ProxyAccessible);
     MOZ_ASSERT(!mWrapper);
   }
 
-  void AddChildAt(uint32_t aIdx, ProxyAccessible* aChild)
+  void AddChildAt(uint32_t aIdx, Derived* aChild)
   { mChildren.InsertElementAt(aIdx, aChild); }
 
   uint32_t ChildrenCount() const { return mChildren.Length(); }
-  ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
-  ProxyAccessible* FirstChild() const
+  Derived* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
+  Derived* FirstChild() const
     { return mChildren.Length() ? mChildren[0] : nullptr; }
-  ProxyAccessible* LastChild() const
+  Derived* LastChild() const
     { return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; }
-  ProxyAccessible* PrevSibling() const
+  Derived* PrevSibling() const
   {
     size_t idx = IndexInParent();
     return idx > 0 ? Parent()->mChildren[idx - 1] : nullptr;
   }
-  ProxyAccessible* NextSibling() const
+  Derived* NextSibling() const
   {
     size_t idx = IndexInParent();
     return idx + 1 < Parent()->mChildren.Length() ? Parent()->mChildren[idx + 1]
     : nullptr;
   }
 
   // XXX evaluate if this is fast enough.
-  size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
+  size_t IndexInParent() const { return
+    Parent()->mChildren.IndexOf(static_cast<const Derived*>(this)); }
   uint32_t EmbeddedChildCount() const;
-  int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
-  ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
+  int32_t IndexOfEmbeddedChild(const Derived* aChild);
+  Derived* EmbeddedChildAt(size_t aChildIdx);
   bool MustPruneChildren() const;
 
   void Shutdown();
 
   void SetChildDoc(DocAccessibleParent*);
 
   /**
    * Remove The given child.
    */
-  void RemoveChild(ProxyAccessible* aChild)
+  void RemoveChild(Derived* aChild)
     { mChildren.RemoveElement(aChild); }
 
   /**
    * Return the proxy for the parent of the wrapped accessible.
    */
-  ProxyAccessible* Parent() const { return mParent; }
+  Derived* Parent() const { return mParent; }
 
   Accessible* OuterDocOfRemoteBrowser() const;
 
   /**
    * Get the role of the accessible we're proxying.
    */
   role Role() const { return mRole; }
 
@@ -113,294 +104,16 @@ public:
   bool IsEmbeddedObject() const
   {
     role role = Role();
     return role != roles::TEXT_LEAF &&
            role != roles::WHITESPACE &&
            role != roles::STATICTEXT;
   }
 
-  /*
-   * Return the states for the proxied accessible.
-   */
-  uint64_t State() const;
-
-  /*
-   * Return the native states for the proxied accessible.
-   */
-  uint64_t NativeState() const;
-
-  /*
-   * Set aName to the name of the proxied accessible.
-   */
-  void Name(nsString& aName) const;
-
-  /*
-   * Set aValue to the value of the proxied accessible.
-   */
-  void Value(nsString& aValue) const;
-
-  /*
-   * Set aHelp to the help string of the proxied accessible.
-   */
-  void Help(nsString& aHelp) const;
-
-  /**
-   * Set aDesc to the description of the proxied accessible.
-   */
-  void Description(nsString& aDesc) const;
-
-  /**
-   * Get the set of attributes on the proxied accessible.
-   */
-  void Attributes(nsTArray<Attribute> *aAttrs) const;
-
-  /**
-   * Return set of targets of given relation type.
-   */
-  nsTArray<ProxyAccessible*> RelationByType(RelationType aType) const;
-
-  /**
-   * Get all relations for this accessible.
-   */
-  void Relations(nsTArray<RelationType>* aTypes,
-                 nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) const;
-
-  bool IsSearchbox() const;
-
-  nsIAtom* LandmarkRole() const;
-
-  nsIAtom* ARIARoleAtom() const;
-
-  int32_t GetLevelInternal();
-  void ScrollTo(uint32_t aScrollType);
-  void ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY);
-
-  int32_t CaretLineNumber();
-  int32_t CaretOffset();
-  void SetCaretOffset(int32_t aOffset);
-
-  int32_t CharacterCount();
-  int32_t SelectionCount();
-
-  /**
-   * Get the text between the given offsets.
-   */
-  bool TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
-                     nsString& aText) const;
-
-  void GetTextAfterOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                          nsString& aText, int32_t* aStartOffset,
-                          int32_t* aEndOffset);
-
-  void GetTextAtOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                       nsString& aText, int32_t* aStartOffset,
-                       int32_t* aEndOffset);
-
-  void GetTextBeforeOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                           nsString& aText, int32_t* aStartOffset,
-                           int32_t* aEndOffset);
-
-  char16_t CharAt(int32_t aOffset);
-
-  void TextAttributes(bool aIncludeDefAttrs,
-                      const int32_t aOffset,
-                      nsTArray<Attribute>* aAttributes,
-                      int32_t* aStartOffset,
-                      int32_t* aEndOffset);
-  void DefaultTextAttributes(nsTArray<Attribute>* aAttrs);
-
-  nsIntRect TextBounds(int32_t aStartOffset, int32_t aEndOffset,
-                       uint32_t aCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE);
-
-  nsIntRect CharBounds(int32_t aOffset, uint32_t aCoordType);
-
-  int32_t OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType);
-
-  bool SelectionBoundsAt(int32_t aSelectionNum,
-                         nsString& aData,
-                         int32_t* aStartOffset,
-                         int32_t* aEndOffset);
-
-  bool SetSelectionBoundsAt(int32_t aSelectionNum,
-                            int32_t aStartOffset,
-                            int32_t aEndOffset);
-
-  bool AddToSelection(int32_t aStartOffset,
-                      int32_t aEndOffset);
-
-  bool RemoveFromSelection(int32_t aSelectionNum);
-
-  void ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset,
-                         uint32_t aScrollType);
-
-  void ScrollSubstringToPoint(int32_t aStartOffset,
-                              int32_t aEndOffset,
-                              uint32_t aCoordinateType,
-                              int32_t aX, int32_t aY);
-
-  void Text(nsString* aText);
-
-  void ReplaceText(const nsString& aText);
-
-  bool InsertText(const nsString& aText, int32_t aPosition);
-
-  bool CopyText(int32_t aStartPos, int32_t aEndPos);
-
-  bool CutText(int32_t aStartPos, int32_t aEndPos);
-
-  bool DeleteText(int32_t aStartPos, int32_t aEndPos);
-
-  bool PasteText(int32_t aPosition);
-
-  nsIntPoint ImagePosition(uint32_t aCoordType);
-
-  nsIntSize ImageSize();
-
-  uint32_t StartOffset(bool* aOk);
-
-  uint32_t EndOffset(bool* aOk);
-
-  bool IsLinkValid();
-
-  // XXX checking mRole alone may not result in same behavior as Accessibles
-  // due to ARIA roles. See bug 1210477.
-  inline bool IsTable() const
-  {
-    return mRole == roles::TABLE || mRole == roles::MATHML_TABLE;
-  }
-  inline bool IsTableRow() const
-  {
-    return (mRole == roles::ROW ||
-            mRole == roles::MATHML_TABLE_ROW ||
-            mRole == roles::MATHML_LABELED_ROW);
-  }
-  inline bool IsTableCell() const
-  {
-    return (mRole == roles::CELL ||
-            mRole == roles::COLUMNHEADER ||
-            mRole == roles::ROWHEADER ||
-            mRole == roles::GRID_CELL ||
-            mRole == roles::MATHML_CELL);
-  }
-
-  uint32_t AnchorCount(bool* aOk);
-
-  void AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk);
-
-  ProxyAccessible* AnchorAt(uint32_t aIndex);
-
-  uint32_t LinkCount();
-
-  ProxyAccessible* LinkAt(const uint32_t& aIndex);
-
-  int32_t LinkIndexOf(ProxyAccessible* aLink);
-
-  int32_t LinkIndexAtOffset(uint32_t aOffset);
-
-  ProxyAccessible* TableOfACell();
-
-  uint32_t ColIdx();
-
-  uint32_t RowIdx();
-
-  uint32_t ColExtent();
-
-  uint32_t RowExtent();
-
-  void ColHeaderCells(nsTArray<ProxyAccessible*>* aCells);
-
-  void RowHeaderCells(nsTArray<ProxyAccessible*>* aCells);
-
-  bool IsCellSelected();
-
-  ProxyAccessible* TableCaption();
-  void TableSummary(nsString& aSummary);
-  uint32_t TableColumnCount();
-  uint32_t TableRowCount();
-  ProxyAccessible* TableCellAt(uint32_t aRow, uint32_t aCol);
-  int32_t TableCellIndexAt(uint32_t aRow, uint32_t aCol);
-  int32_t TableColumnIndexAt(uint32_t aCellIndex);
-  int32_t TableRowIndexAt(uint32_t aCellIndex);
-  void TableRowAndColumnIndicesAt(uint32_t aCellIndex,
-                                  int32_t* aRow, int32_t* aCol);
-  uint32_t TableColumnExtentAt(uint32_t aRow, uint32_t aCol);
-  uint32_t TableRowExtentAt(uint32_t aRow, uint32_t aCol);
-  void TableColumnDescription(uint32_t aCol, nsString& aDescription);
-  void TableRowDescription(uint32_t aRow, nsString& aDescription);
-  bool TableColumnSelected(uint32_t aCol);
-  bool TableRowSelected(uint32_t aRow);
-  bool TableCellSelected(uint32_t aRow, uint32_t aCol);
-  uint32_t TableSelectedCellCount();
-  uint32_t TableSelectedColumnCount();
-  uint32_t TableSelectedRowCount();
-  void TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs);
-  void TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices);
-  void TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices);
-  void TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices);
-  void TableSelectColumn(uint32_t aCol);
-  void TableSelectRow(uint32_t aRow);
-  void TableUnselectColumn(uint32_t aCol);
-  void TableUnselectRow(uint32_t aRow);
-  bool TableIsProbablyForLayout();
-  ProxyAccessible* AtkTableColumnHeader(int32_t aCol);
-  ProxyAccessible* AtkTableRowHeader(int32_t aRow);
-
-  void SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems);
-  uint32_t SelectedItemCount();
-  ProxyAccessible* GetSelectedItem(uint32_t aIndex);
-  bool IsItemSelected(uint32_t aIndex);
-  bool AddItemToSelection(uint32_t aIndex);
-  bool RemoveItemFromSelection(uint32_t aIndex);
-  bool SelectAll();
-  bool UnselectAll();
-
-  void TakeSelection();
-  void SetSelected(bool aSelect);
-
-  bool DoAction(uint8_t aIndex);
-  uint8_t ActionCount();
-  void ActionDescriptionAt(uint8_t aIndex, nsString& aDescription);
-  void ActionNameAt(uint8_t aIndex, nsString& aName);
-  KeyBinding AccessKey();
-  KeyBinding KeyboardShortcut();
-  void AtkKeyBinding(nsString& aBinding);
-
-  double CurValue();
-  bool SetCurValue(double aValue);
-  double MinValue();
-  double MaxValue();
-  double Step();
-
-  void TakeFocus();
-  ProxyAccessible* FocusedChild();
-  ProxyAccessible* ChildAtPoint(int32_t aX, int32_t aY,
-                                Accessible::EWhichChildAtPoint aWhichChild);
-  nsIntRect Bounds();
-
-  void Language(nsString& aLocale);
-  void DocType(nsString& aType);
-  void Title(nsString& aTitle);
-  void URL(nsString& aURL);
-  void MimeType(nsString aMime);
-  void URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
-                          nsString& aMimeType);
-
-  ProxyAccessible* AccessibleAtPoint(int32_t aX, int32_t aY,
-                                     bool aNeedsScreenCoords);
-
-  void Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY,
-               int32_t* aWidth, int32_t* aHeight);
-
-  /**
-   * Return the id of the dom node this accessible represents.  Note this
-   * should probably only be used for testing.
-   */
-  void DOMNodeID(nsString& aID);
-
   /**
    * Allow the platform to store a pointers worth of data on us.
    */
   uintptr_t GetWrapper() const { return mWrapper; }
   void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
 
   /*
    * Return the ID of the accessible being proxied.
@@ -415,40 +128,62 @@ public:
 
   /**
    * Return true if this proxy is a DocAccessibleParent.
    */
   bool IsDoc() const { return mIsDoc; }
   DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; }
 
 protected:
-  explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) :
+  ProxyAccessibleBase(uint64_t aID, Derived* aParent,
+                      DocAccessibleParent* aDoc, role aRole,
+                      uint32_t aInterfaces)
+    : mParent(aParent)
+    , 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),
     mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
     mIsHyperLink(false), mIsHyperText(false)
-  { MOZ_COUNT_CTOR(ProxyAccessible); }
+  {}
 
 protected:
-  ProxyAccessible* mParent;
+  Derived* mParent;
 
 private:
-  nsTArray<ProxyAccessible*> mChildren;
+  friend Derived;
+
+  nsTArray<Derived*> mChildren;
   DocAccessibleParent* mDoc;
   uintptr_t mWrapper;
   uint64_t mID;
+
 protected:
   // XXX DocAccessibleParent gets to change this to change the role of
   // documents.
   role mRole : 27;
+
 private:
   bool mOuterDoc : 1;
 
 public:
   const bool mIsDoc: 1;
   const bool mHasValue: 1;
   const bool mIsHyperLink: 1;
   const bool mIsHyperText: 1;
 };
 
+extern template class ProxyAccessibleBase<ProxyAccessible>;
+
 }
 }
 
 #endif
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -1,53 +1,56 @@
 # -*- 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/.
 
-IPDL_SOURCES += ['PDocAccessible.ipdl']
-
-# with --disable-accessibility we need to compile PDocAccessible.ipdl, but not
-# the C++.
-if CONFIG['ACCESSIBILITY']:
-    EXPORTS.mozilla.a11y += [
-        'DocAccessibleChild.h',
-        'DocAccessibleParent.h',
-        'ProxyAccessible.h'
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DIRS += ['win']
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/win',
+        '/accessible/windows/ia2',
+        '/accessible/windows/msaa',
     ]
-
-    SOURCES += [
-        'DocAccessibleChild.cpp',
-        'DocAccessibleParent.cpp',
-        'ProxyAccessible.cpp'
+else:
+    DIRS += ['other']
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/other',
     ]
-
-    LOCAL_INCLUDES += [
-        '../base',
-        '../generic',
-        '../xpcom',
-    ]
-
     if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         LOCAL_INCLUDES += [
             '/accessible/atk',
         ]
-    elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-        LOCAL_INCLUDES += [
-            '/accessible/windows/ia2',
-            '/accessible/windows/msaa',
-        ]
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         LOCAL_INCLUDES += [
             '/accessible/mac',
         ]
     else:
         LOCAL_INCLUDES += [
             '/accessible/other',
         ]
 
-    FINAL_LIBRARY = 'xul'
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
+
+if CONFIG['ACCESSIBILITY']:
+    EXPORTS.mozilla.a11y += [
+        'DocAccessibleChildBase.h',
+        'DocAccessibleParent.h',
+        'ProxyAccessibleBase.h',
+    ]
+
+    UNIFIED_SOURCES += [
+        'DocAccessibleChildBase.cpp',
+        'DocAccessibleParent.cpp',
+        'ProxyAccessibleBase.cpp',
+    ]
+
+    LOCAL_INCLUDES += [
+        '/accessible/base',
+        '/accessible/generic',
+        '/accessible/xpcom',
+    ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wno-error=shadow']
+FINAL_LIBRARY = 'xul'
rename from accessible/ipc/DocAccessibleChild.cpp
rename to accessible/ipc/other/DocAccessibleChild.cpp
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/other/DocAccessibleChild.cpp
@@ -19,73 +19,16 @@
 #include "nsAccUtils.h"
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "AccessibleWrap.h"
 #endif
 
 namespace mozilla {
 namespace a11y {
 
-static uint32_t
-InterfacesFor(Accessible* aAcc)
-{
-  uint32_t interfaces = 0;
-  if (aAcc->IsHyperText() && aAcc->AsHyperText()->IsTextRole())
-    interfaces |= Interfaces::HYPERTEXT;
-
-  if (aAcc->IsLink())
-    interfaces |= Interfaces::HYPERLINK;
-
-  if (aAcc->HasNumericValue())
-    interfaces |= Interfaces::VALUE;
-
-  if (aAcc->IsImage())
-    interfaces |= Interfaces::IMAGE;
-
-  if (aAcc->IsTable()) {
-    interfaces |= Interfaces::TABLE;
-  }
-
-  if (aAcc->IsTableCell())
-    interfaces |= Interfaces::TABLECELL;
-
-  if (aAcc->IsDoc())
-    interfaces |= Interfaces::DOCUMENT;
-
-  if (aAcc->IsSelect()) {
-    interfaces |= Interfaces::SELECTION;
-  }
-
-  if (aAcc->ActionCount()) {
-    interfaces |= Interfaces::ACTION;
-  }
-
-  return interfaces;
-}
-
-static void
-SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree)
-{
-  uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
-  uint32_t role = aRoot->Role();
-  uint32_t childCount = aRoot->ChildCount();
-  uint32_t interfaces = InterfacesFor(aRoot);
-
-  // OuterDocAccessibles are special because we don't want to serialize the
-  // child doc here, we'll call PDocAccessibleConstructor in
-  // NotificationController.
-  MOZ_ASSERT(!aRoot->IsDoc(), "documents shouldn't be serialized");
-  if (aRoot->IsOuterDoc())
-    childCount = 0;
-
-  aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
-  for (uint32_t i = 0; i < childCount; i++)
-    SerializeTree(aRoot->GetChildAt(i), aTree);
-}
-
 Accessible*
 DocAccessibleChild::IdToAccessible(const uint64_t& aID) const
 {
   if (!aID)
     return mDoc;
 
   if (!mDoc)
     return nullptr;
@@ -137,28 +80,16 @@ DocAccessibleChild::IdToTableCellAccessi
 
 TableAccessible*
 DocAccessibleChild::IdToTableAccessible(const uint64_t& aID) const
 {
   Accessible* acc = IdToAccessible(aID);
   return (acc && acc->IsTable()) ? acc->AsTable() : nullptr;
 }
 
-void
-DocAccessibleChild::ShowEvent(AccShowEvent* aShowEvent)
-{
-  Accessible* parent = aShowEvent->Parent();
-  uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID());
-  uint32_t idxInParent = aShowEvent->InsertionIndex();
-  nsTArray<AccessibleData> shownTree;
-  ShowEventData data(parentID, idxInParent, shownTree);
-  SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
-  SendShowEvent(data, aShowEvent->IsFromUserInput());
-}
-
 bool
 DocAccessibleChild::RecvState(const uint64_t& aID, uint64_t* aState)
 {
   Accessible* acc = IdToAccessible(aID);
   if (!acc) {
     *aState = states::DEFUNCT;
     return true;
   }
rename from accessible/ipc/DocAccessibleChild.h
rename to accessible/ipc/other/DocAccessibleChild.h
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/other/DocAccessibleChild.h
@@ -2,68 +2,46 @@
 /* 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/. */
 
 #ifndef mozilla_a11y_DocAccessibleChild_h
 #define mozilla_a11y_DocAccessibleChild_h
 
-#include "mozilla/a11y/DocAccessible.h"
-#include "mozilla/a11y/PDocAccessibleChild.h"
-#include "nsISupportsImpl.h"
+#include "mozilla/a11y/DocAccessibleChildBase.h"
 
 namespace mozilla {
 namespace a11y {
+
 class Accessible;
 class HyperTextAccessible;
 class TextLeafAccessible;
 class ImageAccessible;
 class TableAccessible;
 class TableCellAccessible;
-class AccShowEvent;
 
-  /*
-   * These objects handle content side communication for an accessible document,
-   * and their lifetime is the same as the document they represent.
-   */
-class DocAccessibleChild : public PDocAccessibleChild
+/*
+ * 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) :
-    mDoc(aDoc)
-  { MOZ_COUNT_CTOR(DocAccessibleChild); }
+  explicit DocAccessibleChild(DocAccessible* aDoc)
+    : DocAccessibleChildBase(aDoc)
+  {
+    MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
+  }
+
   ~DocAccessibleChild()
   {
-    // Shutdown() should have been called, but maybe it isn't if the process is
-    // killed?
-    MOZ_ASSERT(!mDoc);
-    if (mDoc)
-      mDoc->SetIPCDoc(nullptr);
-    MOZ_COUNT_DTOR(DocAccessibleChild);
+    MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
   }
 
-  void Shutdown()
-  {
-    mDoc->SetIPCDoc(nullptr);
-    mDoc = nullptr;
-    SendShutdown();
-  }
-
-  virtual void ActorDestroy(ActorDestroyReason) override
-  {
-    if (!mDoc)
-      return;
-
-    mDoc->SetIPCDoc(nullptr);
-    mDoc = nullptr;
-  }
-
-  void ShowEvent(AccShowEvent* aShowEvent);
-
   /*
    * Return the state for the accessible with given ID.
    */
   virtual bool RecvState(const uint64_t& aID, uint64_t* aState) override;
 
   /*
    * Return the native state for the accessible with given ID.
    */
@@ -491,16 +469,14 @@ private:
   HyperTextAccessible* IdToHyperTextAccessible(const uint64_t& aID) const;
   TextLeafAccessible* IdToTextLeafAccessible(const uint64_t& aID) const;
   ImageAccessible* IdToImageAccessible(const uint64_t& aID) const;
   TableCellAccessible* IdToTableCellAccessible(const uint64_t& aID) const;
   TableAccessible* IdToTableAccessible(const uint64_t& aID) const;
 
   bool PersistentPropertiesToArray(nsIPersistentProperties* aProps,
                                    nsTArray<Attribute>* aAttributes);
-
-  DocAccessible* mDoc;
 };
 
 }
 }
 
 #endif
rename from accessible/ipc/PDocAccessible.ipdl
rename to accessible/ipc/other/PDocAccessible.ipdl
copy from accessible/ipc/ProxyAccessible.cpp
copy to accessible/ipc/other/ProxyAccessible.cpp
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/other/ProxyAccessible.cpp
@@ -1,92 +1,29 @@
 /* -*- 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 "ProxyAccessible.h"
-#include "DocAccessibleParent.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"
 #include "mozilla/a11y/Role.h"
 #include "xpcAccessibleDocument.h"
 
 namespace mozilla {
 namespace a11y {
 
-void
-ProxyAccessible::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(this);
-  }
-
-  // XXX Ideally  this wouldn't be necessary, but it seems OuterDoc accessibles
-  // can be destroyed before the doc they own.
-  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();
-  }
-
-  mChildren.Clear();
-  ProxyDestroyed(this);
-  mDoc->RemoveAccessible(this);
-}
-
-void
-ProxyAccessible::SetChildDoc(DocAccessibleParent* aParent)
-{
-  if (aParent) {
-    MOZ_ASSERT(mChildren.IsEmpty());
-    mChildren.AppendElement(aParent);
-    mOuterDoc = true;
-  } else {
-    MOZ_ASSERT(mChildren.Length() == 1);
-    mChildren.Clear();
-    mOuterDoc = false;
-  }
-}
-
-bool
-ProxyAccessible::MustPruneChildren() const
-{
-  // this is the equivalent to nsAccUtils::MustPrune for proxies and should be
-  // kept in sync with that.
-  if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION
-      && mRole != roles::OPTION && mRole != roles::ENTRY
-      && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT
-      && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON
-      && mRole != roles::GRAPHIC && mRole != roles::SLIDER
-      && mRole != roles::PROGRESSBAR && mRole != roles::SEPARATOR)
-    return false;
-
-  if (mChildren.Length() != 1)
-    return false;
-
-  return mChildren[0]->Role() == roles::TEXT_LEAF
-    || mChildren[0]->Role() == roles::STATICTEXT;
-}
-
 uint64_t
 ProxyAccessible::State() const
 {
   uint64_t state = 0;
   Unused << mDoc->SendState(mID, &state);
   return state;
 }
 
@@ -1027,65 +964,16 @@ ProxyAccessible::Step()
 }
 
 void
 ProxyAccessible::TakeFocus()
 {
   Unused << mDoc->SendTakeFocus(mID);
 }
 
-uint32_t
-ProxyAccessible::EmbeddedChildCount() const
-{
-  size_t count = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (mChildren[i]->IsEmbeddedObject()) {
-      count++;
-    }
-  }
-
-  return count;
-}
-
-int32_t
-ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
-{
-  size_t index = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (mChildren[i]->IsEmbeddedObject()) {
-      if (mChildren[i] == aChild) {
-        return index;
-      }
-
-      index++;
-    }
-  }
-
-  return -1;
-}
-
-ProxyAccessible*
-ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
-{
-  size_t index = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (!mChildren[i]->IsEmbeddedObject()) {
-      continue;
-    }
-
-    if (index == aChildIdx) {
-      return mChildren[i];
-    }
-
-    index++;
-  }
-
-  return nullptr;
-}
-
 ProxyAccessible*
 ProxyAccessible::FocusedChild()
 {
   uint64_t childID = 0;
   bool ok = false;
   Unused << mDoc->SendFocusedChild(mID, &childID, &ok);
   return ok ? mDoc->GetAccessible(childID) : nullptr;
 }
@@ -1170,23 +1058,10 @@ ProxyAccessible::Extents(bool aNeedsScre
 }
 
 void
 ProxyAccessible::DOMNodeID(nsString& aID)
 {
   Unused << mDoc->SendDOMNodeID(mID, &aID);
 }
 
-Accessible*
-ProxyAccessible::OuterDocOfRemoteBrowser() const
-{
-  auto tab = static_cast<dom::TabParent*>(mDoc->Manager());
-  dom::Element* frame = tab->GetOwnerElement();
-  NS_ASSERTION(frame, "why isn't the tab in a frame!");
-  if (!frame)
-    return nullptr;
-
-  DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
-
-  return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
 }
 }
-}
copy from accessible/ipc/ProxyAccessible.h
copy to accessible/ipc/other/ProxyAccessible.h
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/other/ProxyAccessible.h
@@ -2,125 +2,43 @@
 /* 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/. */
 
 #ifndef mozilla_a11y_ProxyAccessible_h
 #define mozilla_a11y_ProxyAccessible_h
 
+#include "Accessible.h"
+#include "mozilla/a11y/ProxyAccessibleBase.h"
 #include "mozilla/a11y/Role.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleTypes.h"
-#include "Accessible.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRect.h"
-#include "Accessible.h"
 
 namespace mozilla {
 namespace a11y {
 
-class Accessible;
-class Attribute;
-class DocAccessibleParent;
-enum class RelationType;
-
-enum Interfaces
-{
-  HYPERTEXT = 1,
-  HYPERLINK = 1 << 1,
-  IMAGE = 1 << 2,
-  VALUE = 1 << 3,
-  TABLE = 1 << 4,
-  TABLECELL = 1 << 5,
-  DOCUMENT = 1 << 6,
-  SELECTION = 1 << 7,
-  ACTION = 1 << 8,
-};
-
-class ProxyAccessible
+class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible>
 {
 public:
 
   ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
-                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) :
-     mParent(aParent), mDoc(aDoc), mWrapper(0), mID(aID), mRole(aRole),
-     mOuterDoc(false), mIsDoc(false),
-     mHasValue(aInterfaces & Interfaces::VALUE),
-     mIsHyperLink(aInterfaces & Interfaces::HYPERLINK),
-     mIsHyperText(aInterfaces & Interfaces::HYPERTEXT)
+                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces)
+    : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
+
   {
     MOZ_COUNT_CTOR(ProxyAccessible);
   }
+
   ~ProxyAccessible()
   {
     MOZ_COUNT_DTOR(ProxyAccessible);
-    MOZ_ASSERT(!mWrapper);
-  }
-
-  void AddChildAt(uint32_t aIdx, ProxyAccessible* aChild)
-  { mChildren.InsertElementAt(aIdx, aChild); }
-
-  uint32_t ChildrenCount() const { return mChildren.Length(); }
-  ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
-  ProxyAccessible* FirstChild() const
-    { return mChildren.Length() ? mChildren[0] : nullptr; }
-  ProxyAccessible* LastChild() const
-    { return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; }
-  ProxyAccessible* PrevSibling() const
-  {
-    size_t idx = IndexInParent();
-    return idx > 0 ? Parent()->mChildren[idx - 1] : nullptr;
-  }
-  ProxyAccessible* NextSibling() const
-  {
-    size_t idx = IndexInParent();
-    return idx + 1 < Parent()->mChildren.Length() ? Parent()->mChildren[idx + 1]
-    : nullptr;
-  }
-
-  // XXX evaluate if this is fast enough.
-  size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
-  uint32_t EmbeddedChildCount() const;
-  int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
-  ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
-  bool MustPruneChildren() const;
-
-  void Shutdown();
-
-  void SetChildDoc(DocAccessibleParent*);
-
-  /**
-   * Remove The given child.
-   */
-  void RemoveChild(ProxyAccessible* aChild)
-    { mChildren.RemoveElement(aChild); }
-
-  /**
-   * Return the proxy for the parent of the wrapped accessible.
-   */
-  ProxyAccessible* Parent() const { return mParent; }
-
-  Accessible* OuterDocOfRemoteBrowser() const;
-
-  /**
-   * Get the role of the accessible we're proxying.
-   */
-  role Role() const { return mRole; }
-
-  /**
-   * Return true if this is an embedded object.
-   */
-  bool IsEmbeddedObject() const
-  {
-    role role = Role();
-    return role != roles::TEXT_LEAF &&
-           role != roles::WHITESPACE &&
-           role != roles::STATICTEXT;
   }
 
   /*
    * Return the states for the proxied accessible.
    */
   uint64_t State() const;
 
   /*
@@ -391,64 +309,18 @@ public:
                int32_t* aWidth, int32_t* aHeight);
 
   /**
    * Return the id of the dom node this accessible represents.  Note this
    * should probably only be used for testing.
    */
   void DOMNodeID(nsString& aID);
 
-  /**
-   * Allow the platform to store a pointers worth of data on us.
-   */
-  uintptr_t GetWrapper() const { return mWrapper; }
-  void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
-
-  /*
-   * Return the ID of the accessible being proxied.
-   */
-  uint64_t ID() const { return mID; }
-
-  /**
-   * Return the document containing this proxy, or the proxy itself if it is a
-   * document.
-   */
-  DocAccessibleParent* Document() const { return mDoc; }
-
-  /**
-   * Return true if this proxy is a DocAccessibleParent.
-   */
-  bool IsDoc() const { return mIsDoc; }
-  DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; }
-
 protected:
-  explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) :
-    mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0),
-    mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
-    mIsHyperLink(false), mIsHyperText(false)
+  explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
+    : ProxyAccessibleBase(aThisAsDoc)
   { MOZ_COUNT_CTOR(ProxyAccessible); }
-
-protected:
-  ProxyAccessible* mParent;
-
-private:
-  nsTArray<ProxyAccessible*> mChildren;
-  DocAccessibleParent* mDoc;
-  uintptr_t mWrapper;
-  uint64_t mID;
-protected:
-  // XXX DocAccessibleParent gets to change this to change the role of
-  // documents.
-  role mRole : 27;
-private:
-  bool mOuterDoc : 1;
-
-public:
-  const bool mIsDoc: 1;
-  const bool mHasValue: 1;
-  const bool mIsHyperLink: 1;
-  const bool mIsHyperText: 1;
 };
 
 }
 }
 
 #endif
copy from accessible/ipc/moz.build
copy to accessible/ipc/other/moz.build
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/other/moz.build
@@ -1,53 +1,47 @@
 # -*- 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/.
 
+# With --disable-accessibility, we need to compile PDocAccessible.ipdl, but
+# not the C++.
 IPDL_SOURCES += ['PDocAccessible.ipdl']
 
-# with --disable-accessibility we need to compile PDocAccessible.ipdl, but not
-# the C++.
 if CONFIG['ACCESSIBILITY']:
     EXPORTS.mozilla.a11y += [
         'DocAccessibleChild.h',
-        'DocAccessibleParent.h',
-        'ProxyAccessible.h'
+        'ProxyAccessible.h',
     ]
 
     SOURCES += [
         'DocAccessibleChild.cpp',
-        'DocAccessibleParent.cpp',
-        'ProxyAccessible.cpp'
+        'ProxyAccessible.cpp',
     ]
 
     LOCAL_INCLUDES += [
-        '../base',
-        '../generic',
-        '../xpcom',
+        '../../base',
+        '../../generic',
+        '../../xpcom',
     ]
 
     if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
         LOCAL_INCLUDES += [
             '/accessible/atk',
         ]
-    elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-        LOCAL_INCLUDES += [
-            '/accessible/windows/ia2',
-            '/accessible/windows/msaa',
-        ]
     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         LOCAL_INCLUDES += [
             '/accessible/mac',
         ]
     else:
         LOCAL_INCLUDES += [
             '/accessible/other',
         ]
 
-    FINAL_LIBRARY = 'xul'
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
+
+FINAL_LIBRARY = 'xul'
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/COMPtrTypes.cpp
@@ -0,0 +1,50 @@
+/* -*- 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 "mozilla/a11y/COMPtrTypes.h"
+
+#include "MainThreadUtils.h"
+#include "mozilla/a11y/Accessible.h"
+#include "mozilla/Move.h"
+#include "mozilla/mscom/MainThreadHandoff.h"
+#include "mozilla/RefPtr.h"
+
+using mozilla::mscom::MainThreadHandoff;
+using mozilla::mscom::STAUniquePtr;
+
+namespace mozilla {
+namespace a11y {
+
+IAccessibleHolder
+CreateHolderFromAccessible(Accessible* aAccToWrap)
+{
+  MOZ_ASSERT(aAccToWrap && NS_IsMainThread());
+  if (!aAccToWrap) {
+    return nullptr;
+  }
+
+  IAccessible* rawNative = nullptr;
+  aAccToWrap->GetNativeInterface((void**)&rawNative);
+  MOZ_ASSERT(rawNative);
+  if (!rawNative) {
+    return nullptr;
+  }
+
+  STAUniquePtr<IAccessible> iaToProxy(rawNative);
+
+  IAccessible* rawIntercepted = nullptr;
+  HRESULT hr = MainThreadHandoff::WrapInterface(iaToProxy, &rawIntercepted);
+  MOZ_ASSERT(SUCCEEDED(hr));
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  IAccessibleHolder::COMPtrType iaIntercepted(rawIntercepted);
+  return IAccessibleHolder(Move(iaIntercepted));
+}
+
+} // namespace a11y
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/COMPtrTypes.h
@@ -0,0 +1,27 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_COMPtrTypes_h
+#define mozilla_a11y_COMPtrTypes_h
+
+#include "mozilla/mscom/COMPtrHolder.h"
+
+#include <oleacc.h>
+
+namespace mozilla {
+namespace a11y {
+
+typedef mozilla::mscom::COMPtrHolder<IAccessible, IID_IAccessible> IAccessibleHolder;
+
+class Accessible;
+
+IAccessibleHolder
+CreateHolderFromAccessible(Accessible* aAccToWrap);
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_COMPtrTypes_h
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -0,0 +1,43 @@
+/* -*- 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 "DocAccessibleChild.h"
+
+#include "Accessible-inl.h"
+#include "mozilla/a11y/PlatformChild.h"
+#include "mozilla/ClearOnShutdown.h"
+
+namespace mozilla {
+namespace a11y {
+
+static StaticAutoPtr<PlatformChild> sPlatformChild;
+
+DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
+  : DocAccessibleChildBase(aDoc)
+{
+  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)
+{
+  IAccessibleHolder parentProxy;
+  PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy);
+  mParentProxy.reset(parentProxy.Release());
+}
+
+} // namespace a11y
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -0,0 +1,37 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_DocAccessibleChild_h
+#define mozilla_a11y_DocAccessibleChild_h
+
+#include "mozilla/a11y/COMPtrTypes.h"
+#include "mozilla/a11y/DocAccessibleChildBase.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);
+  IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }
+
+private:
+  mscom::ProxyUniquePtr<IAccessible> mParentProxy;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_DocAccessibleChild_h
copy from accessible/ipc/PDocAccessible.ipdl
copy to accessible/ipc/win/PDocAccessible.ipdl
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -1,54 +1,44 @@
 /* -*- 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 protocol PFileDescriptorSet;
 include protocol PBrowser;
 
-include "mozilla/GfxMessageUtils.h";
-
-using nsIntRect from "nsRect.h";
-using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
-using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h";
+using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/COMPtrTypes.h";
 
 namespace mozilla {
 namespace a11y {
 
 struct AccessibleData
 {
   uint64_t ID;
   uint32_t Role;
   uint32_t ChildrenCount;
   uint32_t Interfaces;
+  IAccessibleHolder COMProxy;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
 };
 
 struct Attribute
 {
   nsCString Name;
   nsString Value;
 };
 
-struct RelationTargets
-{
-  uint32_t Type;
-  uint64_t[] Targets;
-};
-
-prio(normal upto high) sync protocol PDocAccessible
+sync protocol PDocAccessible
 {
   manager PBrowser;
 
 parent:
   async Shutdown();
 
   /*
    * Notify the parent process the document in the child process is firing an
@@ -65,197 +55,19 @@ parent:
   async RoleChangedEvent(uint32_t aRole);
 
   /*
    * Tell the parent document to bind the existing document as a new child
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
+  // 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 __delete__();
-
-  // Accessible
-  prio(high) sync State(uint64_t aID) returns(uint64_t states);
-  prio(high) sync NativeState(uint64_t aID) returns(uint64_t states);
-  prio(high) sync Name(uint64_t aID) returns(nsString name);
-  prio(high) sync Value(uint64_t aID) returns(nsString value);
-  prio(high) sync Help(uint64_t aID) returns(nsString help);
-  prio(high) sync Description(uint64_t aID) returns(nsString desc);
-  prio(high) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
-  prio(high) sync RelationByType(uint64_t aID, uint32_t aRelationType)
-    returns(uint64_t[] targets);
-  prio(high) sync Relations(uint64_t aID) returns(RelationTargets[] relations);
-  prio(high) sync IsSearchbox(uint64_t aID) returns(bool retval);
-  prio(high) sync LandmarkRole(uint64_t aID) returns(nsString landmark);
-  prio(high) sync ARIARoleAtom(uint64_t aID) returns(nsString role);
-  prio(high) sync GetLevelInternal(uint64_t aID) returns(int32_t aLevel);
-  async ScrollTo(uint64_t aID, uint32_t aScrollType);
-  async ScrollToPoint(uint64_t aID, uint32_t aScrollType, int32_t aX,
-                      int32_t aY);
-
-  // AccessibleText
-
-  // TextSubstring is getText in IDL.
-  prio(high) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber);
-  prio(high) sync CaretOffset(uint64_t aID) returns(int32_t aOffset);
-   async SetCaretOffset(uint64_t aID, int32_t aOffset);
-  prio(high) sync CharacterCount(uint64_t aID) returns(int32_t aCount);
-  prio(high) sync SelectionCount(uint64_t aID) returns(int32_t aCount);
-  prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
-                                aEndOffset) returns(nsString aText, bool aValid);
-  prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
-    returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
-    returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
-
-  prio(high) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
-    returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync CharAt(uint64_t aID, int32_t aOffset) returns(uint16_t aChar);
-
-  prio(high) sync TextAttributes(uint64_t aID, bool aIncludeDefAttrs, int32_t aOffset)
-    returns(Attribute[] aAttributes, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync DefaultTextAttributes(uint64_t aID) returns(Attribute[] aAttributes);
-
-  prio(high) sync TextBounds(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset,
-                             uint32_t aCoordType)
-    returns(nsIntRect aRetVal);
-  prio(high) sync CharBounds(uint64_t aID, int32_t aOffset, uint32_t aCoordType)
-    returns(nsIntRect aRetVal);
-
-  prio(high) sync OffsetAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aCoordType)
-    returns(int32_t aRetVal);
-
-  prio(high) sync SelectionBoundsAt(uint64_t aID, int32_t aSelectionNum)
-    returns(bool aSucceeded, nsString aData, int32_t aStartOffset, int32_t aEndOffset);
-  prio(high) sync SetSelectionBoundsAt(uint64_t aID, int32_t aSelectionNum,
-                                       int32_t aStartOffset, int32_t aEndOffset)
-    returns(bool aSucceeded);
-  prio(high) sync AddToSelection(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset)
-    returns(bool aSucceeded);
-  prio(high) sync RemoveFromSelection(uint64_t aID, int32_t aSelectionNum)
-    returns(bool aSucceeded);
-
-  async ScrollSubstringTo(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset,
-                          uint32_t aScrollType);
-  async ScrollSubstringToPoint(uint64_t aID,
-                               int32_t aStartOffset,
-                               int32_t aEndOffset,
-                               uint32_t aCoordinateType,
-                               int32_t aX, int32_t aY);
-
-  prio(high) sync Text(uint64_t aID) returns(nsString aText);
-  prio(high) sync ReplaceText(uint64_t aID, nsString aText);
-  prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition)
-    returns(bool aValid);
-  prio(high) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
-    returns(bool aValid);
-  prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
-    returns(bool aValid);
-  prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
-    returns(bool aValid);
-  prio(high) sync PasteText(uint64_t aID, int32_t aPosition)
-    returns(bool aValid);
-
-  prio(high) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(IntPoint aRetVal);
-  prio(high) sync ImageSize(uint64_t aID) returns(IntSize aRetVal);
-
-  prio(high) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync IsLinkValid(uint64_t aID) returns(bool aRetVal);
-  prio(high) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
-  prio(high) sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk);
-  prio(high) sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk);
-
-  prio(high) sync LinkCount(uint64_t aID) returns(uint32_t aCount);
-  prio(high) sync LinkAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfLink, bool aOk);
-  prio(high) sync LinkIndexOf(uint64_t aID, uint64_t aLinkID) returns(int32_t aIndex);
-  prio(high) sync LinkIndexAtOffset(uint64_t aID, uint32_t aOffset) returns(int32_t aIndex);
-
-  prio(high) sync TableOfACell(uint64_t aID) returns(uint64_t aTableID, bool aOk);
-  prio(high) sync ColIdx(uint64_t aID) returns(uint32_t aIndex);
-  prio(high) sync RowIdx(uint64_t aID) returns(uint32_t aIndex);
-  prio(high) sync ColExtent(uint64_t aID) returns(uint32_t aExtent);
-  prio(high) sync RowExtent(uint64_t aID) returns(uint32_t aExtent);
-  prio(high) sync ColHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
-  prio(high) sync RowHeaderCells(uint64_t aID) returns(uint64_t[] aCells);
-  prio(high) sync IsCellSelected(uint64_t aID) returns(bool aSelected);
-
-  prio(high) sync TableCaption(uint64_t aID) returns(uint64_t aCaptionID, bool aOk);
-  prio(high) sync TableSummary(uint64_t aID) returns(nsString aSummary);
-  prio(high) sync TableColumnCount(uint64_t aID) returns(uint32_t aColCount);
-  prio(high) sync TableRowCount(uint64_t aID) returns(uint32_t aRowCount);
-  prio(high) sync TableCellAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint64_t aCellID, bool aOk);
-  prio(high) sync TableCellIndexAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(int32_t aIndex);
-  prio(high) sync TableColumnIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aCol);
-  prio(high) sync TableRowIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow);
-  prio(high) sync TableRowAndColumnIndicesAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow, int32_t aCol);
-  prio(high) sync TableColumnExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
-  prio(high) sync TableRowExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent);
-  prio(high) sync TableColumnDescription(uint64_t aID, uint32_t aCol) returns(nsString aDescription);
-  prio(high) sync TableRowDescription(uint64_t aID, uint32_t aRow) returns(nsString aDescription);
-  prio(high) sync TableColumnSelected(uint64_t aID, uint32_t aCol) returns(bool aSelected);
-  prio(high) sync TableRowSelected(uint64_t aID, uint32_t aRow) returns(bool aSelected);
-  prio(high) sync TableCellSelected(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(bool aSelected);
-  prio(high) sync TableSelectedCellCount(uint64_t aID) returns(uint32_t aSelectedCells);
-  prio(high) sync TableSelectedColumnCount(uint64_t aID) returns(uint32_t aSelectedColumns);
-  prio(high) sync TableSelectedRowCount(uint64_t aID) returns(uint32_t aSelectedRows);
-  prio(high) sync TableSelectedCells(uint64_t aID) returns(uint64_t[] aCellIDs);
-  prio(high) sync TableSelectedCellIndices(uint64_t aID) returns(uint32_t[] aCellIndeces);
-  prio(high) sync TableSelectedColumnIndices(uint64_t aID) returns(uint32_t[] aColumnIndeces);
-  prio(high) sync TableSelectedRowIndices(uint64_t aID) returns(uint32_t[] aRowIndeces);
-  prio(high) sync TableSelectColumn(uint64_t aID, uint32_t aCol);
-  prio(high) sync TableSelectRow(uint64_t aID, uint32_t aRow);
-  prio(high) sync TableUnselectColumn(uint64_t aID, uint32_t aCol);
-  prio(high) sync TableUnselectRow(uint64_t aID, uint32_t aRow);
-  prio(high) sync TableIsProbablyForLayout(uint64_t aID) returns(bool aForLayout);
-  prio(high) sync AtkTableColumnHeader(uint64_t aID, int32_t aCol)
-    returns(uint64_t aHeaderID, bool aOk);
-  prio(high) sync AtkTableRowHeader(uint64_t aID, int32_t aRow)
-    returns(uint64_t aHeaderID, bool aOk);
-
-  prio(high) sync SelectedItems(uint64_t aID) returns(uint64_t[] aSelectedItemIDs);
-  prio(high) sync SelectedItemCount(uint64_t aID) returns(uint32_t aCount);
-  prio(high) sync GetSelectedItem(uint64_t aID, uint32_t aIndex) returns(uint64_t aSelected, bool aOk);
-  prio(high) sync IsItemSelected(uint64_t aID, uint32_t aIndex) returns(bool aSelected);
-  prio(high) sync AddItemToSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
-  prio(high) sync RemoveItemFromSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess);
-  prio(high) sync SelectAll(uint64_t aID) returns(bool aSuccess);
-  prio(high) sync UnselectAll(uint64_t aID) returns(bool aSuccess);
-
-  async TakeSelection(uint64_t aID);
-  async SetSelected(uint64_t aID, bool aSelected);
-
-  prio(high) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
-  prio(high) sync ActionCount(uint64_t aID) returns(uint8_t aCount);
-  prio(high) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription);
-  prio(high) sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName);
-  prio(high) sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
-  prio(high) sync KeyboardShortcut(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);
-  prio(high) sync AtkKeyBinding(uint64_t aID) returns(nsString aResult);
-
-  prio(high) sync CurValue(uint64_t aID) returns(double aValue);
-  prio(high) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
-  prio(high) sync MinValue(uint64_t aID) returns(double aValue);
-  prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
-  prio(high) sync Step(uint64_t aID) returns(double aStep);
-
-  async TakeFocus(uint64_t aID);
-  prio(high) sync FocusedChild(uint64_t aID)
-    returns(uint64_t aChild, bool aOk);
-
-  prio(high) sync Language(uint64_t aID) returns(nsString aLocale);
-  prio(high) sync DocType(uint64_t aID) returns(nsString aType);
-  prio(high) sync Title(uint64_t aID) returns(nsString aTitle);
-  prio(high) sync URL(uint64_t aID) returns(nsString aURL);
-  prio(high) sync MimeType(uint64_t aID) returns(nsString aMime);
-  prio(high) sync URLDocTypeMimeType(uint64_t aID) returns(nsString aURL, nsString aDocType, nsString aMimeType);
-
-  prio(high) sync AccessibleAtPoint(uint64_t aID, int32_t aX, int32_t aY, bool aNeedsScreenCoords, uint32_t aWhich)
-    returns(uint64_t aResult, bool aOk);
-
-  prio(high) sync Extents(uint64_t aID, bool aNeedsScreenCoords)
-    returns(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight);
-  prio(high) sync DOMNodeID(uint64_t aID) returns(nsString aDOMNodeID);
 };
 
 }
 }
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -0,0 +1,58 @@
+/* -*- 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 "mozilla/a11y/PlatformChild.h"
+#include "mozilla/mscom/EnsureMTA.h"
+#include "mozilla/mscom/InterceptorLog.h"
+
+#include "Accessible2.h"
+#include "Accessible2_2.h"
+#include "AccessibleHypertext2.h"
+#include "AccessibleTableCell.h"
+
+#include "AccessibleHypertext2_i.c"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Unfortunately the COM interceptor does not intrinsically handle array
+ * outparams. Instead we manually define the relevant metadata here, and
+ * register it in a call to mozilla::mscom::RegisterArrayData.
+ * @see mozilla::mscom::ArrayData
+ */
+static const mozilla::mscom::ArrayData sPlatformChildArrayData[] = {
+  {IID_IEnumVARIANT, 3, 1, VT_DISPATCH, IID_IDispatch, 2},
+  {IID_IAccessible2, 30, 1, VT_UNKNOWN | VT_BYREF, IID_IAccessibleRelation, 2},
+  {IID_IAccessibleRelation, 7, 1, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 2},
+  {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3},
+  {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
+  {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
+  {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1}
+};
+
+// 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"))
+{
+  mozilla::mscom::InterceptorLog::Init();
+  mozilla::mscom::RegisterArrayData(sPlatformChildArrayData);
+
+  UniquePtr<mozilla::mscom::RegisteredProxy> ia2Proxy;
+  mozilla::mscom::EnsureMTA([&ia2Proxy]() -> void {
+    ia2Proxy = Move(mozilla::mscom::RegisterProxy(L"ia2marshal.dll"));
+  });
+  mIA2Proxy = Move(ia2Proxy);
+}
+
+} // namespace a11y
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/PlatformChild.h
@@ -0,0 +1,35 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_PlatformChild_h
+#define mozilla_a11y_PlatformChild_h
+
+#include "mozilla/mscom/Registration.h"
+
+namespace mozilla {
+namespace a11y {
+
+class PlatformChild
+{
+public:
+  PlatformChild();
+
+  PlatformChild(PlatformChild&) = delete;
+  PlatformChild(PlatformChild&&) = delete;
+  PlatformChild& operator=(PlatformChild&) = delete;
+  PlatformChild& operator=(PlatformChild&&) = delete;
+
+private:
+  UniquePtr<mozilla::mscom::RegisteredProxy> mIA2Proxy;
+  UniquePtr<mozilla::mscom::RegisteredProxy> mAccTypelib;
+  UniquePtr<mozilla::mscom::RegisteredProxy> mMiscTypelib;
+};
+
+} // namespace mozilla
+} // namespace a11y
+
+#endif // mozilla_a11y_PlatformChild_h
+
copy from accessible/ipc/ProxyAccessible.cpp
copy to accessible/ipc/win/ProxyAccessible.cpp
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/win/ProxyAccessible.cpp
@@ -1,1192 +1,280 @@
 /* -*- 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 "DocAccessibleParent.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"
 #include "mozilla/a11y/Role.h"
 #include "xpcAccessibleDocument.h"
 
+#include <comutil.h>
+
 namespace mozilla {
 namespace a11y {
 
-void
-ProxyAccessible::Shutdown()
+bool
+ProxyAccessible::GetCOMInterface(void** aOutAccessible) const
 {
-  MOZ_DIAGNOSTIC_ASSERT(!IsDoc());
-  NS_ASSERTION(!mOuterDoc, "Why do we still have a child doc?");
-  xpcAccessibleDocument* xpcDoc =
-    GetAccService()->GetCachedXPCDocument(Document());
-  if (xpcDoc) {
-    xpcDoc->NotifyOfShutdown(this);
+  if (!aOutAccessible) {
+    return false;
+  }
+  RefPtr<IAccessible> addRefed = mCOMProxy;
+  addRefed.forget(aOutAccessible);
+  return !!mCOMProxy;
+}
+
+void
+ProxyAccessible::Name(nsString& aName) const
+{
+  aName.Truncate();
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return;
   }
 
-  // XXX Ideally  this wouldn't be necessary, but it seems OuterDoc accessibles
-  // can be destroyed before the doc they own.
-  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();
+  VARIANT id;
+  id.vt = VT_I4;
+  id.lVal = CHILDID_SELF;
+  BSTR result;
+  HRESULT hr = acc->get_accName(id, &result);
+  _bstr_t resultWrap(result, false);
+  if (FAILED(hr)) {
+    return;
   }
-
-  mChildren.Clear();
-  ProxyDestroyed(this);
-  mDoc->RemoveAccessible(this);
+  aName = (wchar_t*)resultWrap;
 }
 
 void
-ProxyAccessible::SetChildDoc(DocAccessibleParent* aParent)
+ProxyAccessible::Value(nsString& aValue) const
 {
-  if (aParent) {
-    MOZ_ASSERT(mChildren.IsEmpty());
-    mChildren.AppendElement(aParent);
-    mOuterDoc = true;
-  } else {
-    MOZ_ASSERT(mChildren.Length() == 1);
-    mChildren.Clear();
-    mOuterDoc = false;
+  aValue.Truncate();
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return;
   }
+
+  VARIANT id;
+  id.vt = VT_I4;
+  id.lVal = CHILDID_SELF;
+  BSTR result;
+  HRESULT hr = acc->get_accValue(id, &result);
+  _bstr_t resultWrap(result, false);
+  if (FAILED(hr)) {
+    return;
+  }
+  aValue = (wchar_t*)resultWrap;
 }
 
-bool
-ProxyAccessible::MustPruneChildren() const
+void
+ProxyAccessible::Description(nsString& aDesc) const
 {
-  // this is the equivalent to nsAccUtils::MustPrune for proxies and should be
-  // kept in sync with that.
-  if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION
-      && mRole != roles::OPTION && mRole != roles::ENTRY
-      && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT
-      && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON
-      && mRole != roles::GRAPHIC && mRole != roles::SLIDER
-      && mRole != roles::PROGRESSBAR && mRole != roles::SEPARATOR)
-    return false;
+  aDesc.Truncate();
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return;
+  }
 
-  if (mChildren.Length() != 1)
-    return false;
-
-  return mChildren[0]->Role() == roles::TEXT_LEAF
-    || mChildren[0]->Role() == roles::STATICTEXT;
+  VARIANT id;
+  id.vt = VT_I4;
+  id.lVal = CHILDID_SELF;
+  BSTR result;
+  HRESULT hr = acc->get_accDescription(id, &result);
+  _bstr_t resultWrap(result, false);
+  if (FAILED(hr)) {
+    return;
+  }
+  aDesc = (wchar_t*)resultWrap;
 }
 
 uint64_t
 ProxyAccessible::State() const
 {
   uint64_t state = 0;
-  Unused << mDoc->SendState(mID, &state);
-  return state;
-}
-
-uint64_t
-ProxyAccessible::NativeState() const
-{
-  uint64_t state = 0;
-  Unused << mDoc->SendNativeState(mID, &state);
-  return state;
-}
-
-void
-ProxyAccessible::Name(nsString& aName) const
-{
-  Unused << mDoc->SendName(mID, &aName);
-}
-
-void
-ProxyAccessible::Value(nsString& aValue) const
-{
-  Unused << mDoc->SendValue(mID, &aValue);
-}
-
-void
-ProxyAccessible::Help(nsString& aHelp) const
-{
-  Unused << mDoc->SendHelp(mID, &aHelp);
-}
-
-void
-ProxyAccessible::Description(nsString& aDesc) const
-{
-  Unused << mDoc->SendDescription(mID, &aDesc);
-}
-
-void
-ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const
-{
-  Unused << mDoc->SendAttributes(mID, aAttrs);
-}
-
-nsTArray<ProxyAccessible*>
-ProxyAccessible::RelationByType(RelationType aType) const
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendRelationByType(mID, static_cast<uint32_t>(aType),
-                                     &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  nsTArray<ProxyAccessible*> targets(targetCount);
-  for (size_t i = 0; i < targetCount; i++)
-    if (ProxyAccessible* proxy = mDoc->GetAccessible(targetIDs[i]))
-      targets.AppendElement(proxy);
-
-  return Move(targets);
-}
-
-void
-ProxyAccessible::Relations(nsTArray<RelationType>* aTypes,
-                           nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets)
-  const
-{
-  nsTArray<RelationTargets> ipcRelations;
-  Unused << mDoc->SendRelations(mID, &ipcRelations);
-
-  size_t relationCount = ipcRelations.Length();
-  aTypes->SetCapacity(relationCount);
-  aTargetSets->SetCapacity(relationCount);
-  for (size_t i = 0; i < relationCount; i++) {
-    uint32_t type = ipcRelations[i].Type();
-    if (type > static_cast<uint32_t>(RelationType::LAST))
-      continue;
-
-    size_t targetCount = ipcRelations[i].Targets().Length();
-    nsTArray<ProxyAccessible*> targets(targetCount);
-    for (size_t j = 0; j < targetCount; j++)
-      if (ProxyAccessible* proxy = mDoc->GetAccessible(ipcRelations[i].Targets()[j]))
-        targets.AppendElement(proxy);
-
-    if (targets.IsEmpty())
-      continue;
-
-    aTargetSets->AppendElement(Move(targets));
-    aTypes->AppendElement(static_cast<RelationType>(type));
-  }
-}
-
-bool
-ProxyAccessible::IsSearchbox() const
-{
-  bool retVal = false;
-  Unused << mDoc->SendIsSearchbox(mID, &retVal);
-  return retVal;
-}
-
-nsIAtom*
-ProxyAccessible::LandmarkRole() const
-{
-  nsString landmark;
-  Unused << mDoc->SendLandmarkRole(mID, &landmark);
-  return NS_GetStaticAtom(landmark);
-}
-
-nsIAtom*
-ProxyAccessible::ARIARoleAtom() const
-{
-  nsString role;
-  Unused << mDoc->SendARIARoleAtom(mID, &role);
-  return NS_GetStaticAtom(role);
-}
-
-int32_t
-ProxyAccessible::GetLevelInternal()
-{
-  int32_t level = 0;
-  Unused << mDoc->SendGetLevelInternal(mID, &level);
-  return level;
-}
-
-void
-ProxyAccessible::ScrollTo(uint32_t aScrollType)
-{
-  Unused << mDoc->SendScrollTo(mID, aScrollType);
-}
-
-void
-ProxyAccessible::ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY)
-{
-  Unused << mDoc->SendScrollToPoint(mID, aScrollType, aX, aY);
-}
-
-int32_t
-ProxyAccessible::CaretLineNumber()
-{
-  int32_t line = -1;
-  Unused << mDoc->SendCaretOffset(mID, &line);
-  return line;
-}
-
-int32_t
-ProxyAccessible::CaretOffset()
-{
-  int32_t offset = 0;
-  Unused << mDoc->SendCaretOffset(mID, &offset);
-  return offset;
-}
-
-void
-ProxyAccessible::SetCaretOffset(int32_t aOffset)
-{
-  Unused << mDoc->SendSetCaretOffset(mID, aOffset);
-}
-
-int32_t
-ProxyAccessible::CharacterCount()
-{
-  int32_t count = 0;
-  Unused << mDoc->SendCharacterCount(mID, &count);
-  return count;
-}
-
-int32_t
-ProxyAccessible::SelectionCount()
-{
-  int32_t count = 0;
-  Unused << mDoc->SendSelectionCount(mID, &count);
-  return count;
-}
-
-bool
-ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
-                               nsString& aText) const
-{
-  bool valid;
-  Unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText, &valid);
-  return valid;
-}
-
-void
-ProxyAccessible::GetTextAfterOffset(int32_t aOffset,
-                                    AccessibleTextBoundary aBoundaryType,
-                                    nsString& aText, int32_t* aStartOffset,
-                                    int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextAfterOffset(mID, aOffset, aBoundaryType,
-                                         &aText, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::GetTextAtOffset(int32_t aOffset,
-                                 AccessibleTextBoundary aBoundaryType,
-                                 nsString& aText, int32_t* aStartOffset,
-                                 int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextAtOffset(mID, aOffset, aBoundaryType,
-                                      &aText, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::GetTextBeforeOffset(int32_t aOffset,
-                                     AccessibleTextBoundary aBoundaryType,
-                                     nsString& aText, int32_t* aStartOffset,
-                                     int32_t* aEndOffset)
-{
-  Unused << mDoc->SendGetTextBeforeOffset(mID, aOffset, aBoundaryType,
-                                          &aText, aStartOffset, aEndOffset);
-}
-
-char16_t
-ProxyAccessible::CharAt(int32_t aOffset)
-{
-  uint16_t retval = 0;
-  Unused << mDoc->SendCharAt(mID, aOffset, &retval);
-  return static_cast<char16_t>(retval);
-}
-
-void
-ProxyAccessible::TextAttributes(bool aIncludeDefAttrs,
-                                int32_t aOffset,
-                                nsTArray<Attribute>* aAttributes,
-                                int32_t* aStartOffset,
-                                int32_t* aEndOffset)
-{
-  Unused << mDoc->SendTextAttributes(mID, aIncludeDefAttrs, aOffset,
-                                     aAttributes, aStartOffset, aEndOffset);
-}
-
-void
-ProxyAccessible::DefaultTextAttributes(nsTArray<Attribute>* aAttrs)
-{
-  Unused << mDoc->SendDefaultTextAttributes(mID, aAttrs);
-}
-
-nsIntRect
-ProxyAccessible::TextBounds(int32_t aStartOffset, int32_t aEndOffset,
-                            uint32_t aCoordType)
-{
-  nsIntRect rect;
-  Unused <<
-    mDoc->SendTextBounds(mID, aStartOffset, aEndOffset, aCoordType, &rect);
-  return rect;
-}
-
-nsIntRect
-ProxyAccessible::CharBounds(int32_t aOffset, uint32_t aCoordType)
-{
-  nsIntRect rect;
-  Unused <<
-    mDoc->SendCharBounds(mID, aOffset, aCoordType, &rect);
-  return rect;
-}
-
-int32_t
-ProxyAccessible::OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType)
-{
-  int32_t retVal = -1;
-  Unused << mDoc->SendOffsetAtPoint(mID, aX, aY, aCoordType, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::SelectionBoundsAt(int32_t aSelectionNum,
-                                   nsString& aData,
-                                   int32_t* aStartOffset,
-                                   int32_t* aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendSelectionBoundsAt(mID, aSelectionNum, &retVal, &aData,
-                                        aStartOffset, aEndOffset);
-  return retVal;
-}
-
-bool
-ProxyAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
-                                      int32_t aStartOffset,
-                                      int32_t aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendSetSelectionBoundsAt(mID, aSelectionNum, aStartOffset,
-                                           aEndOffset, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::AddToSelection(int32_t aStartOffset,
-                                int32_t aEndOffset)
-{
-  bool retVal = false;
-  Unused << mDoc->SendAddToSelection(mID, aStartOffset, aEndOffset, &retVal);
-  return retVal;
-}
-
-bool
-ProxyAccessible::RemoveFromSelection(int32_t aSelectionNum)
-{
-  bool retVal = false;
-  Unused << mDoc->SendRemoveFromSelection(mID, aSelectionNum, &retVal);
-  return retVal;
-}
-
-void
-ProxyAccessible::ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset,
-                                   uint32_t aScrollType)
-{
-  Unused << mDoc->SendScrollSubstringTo(mID, aStartOffset, aEndOffset, aScrollType);
-}
-
-void
-ProxyAccessible::ScrollSubstringToPoint(int32_t aStartOffset,
-                                        int32_t aEndOffset,
-                                        uint32_t aCoordinateType,
-                                        int32_t aX, int32_t aY)
-{
-  Unused << mDoc->SendScrollSubstringToPoint(mID, aStartOffset, aEndOffset,
-                                             aCoordinateType, aX, aY);
-}
-
-void
-ProxyAccessible::Text(nsString* aText)
-{
-  Unused << mDoc->SendText(mID, aText);
-}
-
-void
-ProxyAccessible::ReplaceText(const nsString& aText)
-{
-  Unused << mDoc->SendReplaceText(mID, aText);
-}
-
-bool
-ProxyAccessible::InsertText(const nsString& aText, int32_t aPosition)
-{
-  bool valid;
-  Unused << mDoc->SendInsertText(mID, aText, aPosition, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::CopyText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendCopyText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::CutText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendCutText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::DeleteText(int32_t aStartPos, int32_t aEndPos)
-{
-  bool valid;
-  Unused << mDoc->SendDeleteText(mID, aStartPos, aEndPos, &valid);
-  return valid;
-}
-
-bool
-ProxyAccessible::PasteText(int32_t aPosition)
-{
-  bool valid;
-  Unused << mDoc->SendPasteText(mID, aPosition, &valid);
-  return valid;
-}
-
-nsIntPoint
-ProxyAccessible::ImagePosition(uint32_t aCoordType)
-{
-  nsIntPoint retVal;
-  Unused << mDoc->SendImagePosition(mID, aCoordType, &retVal);
-  return retVal;
-}
-
-nsIntSize
-ProxyAccessible::ImageSize()
-{
-  nsIntSize retVal;
-  Unused << mDoc->SendImageSize(mID, &retVal);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::StartOffset(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendStartOffset(mID, &retVal, aOk);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::EndOffset(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendEndOffset(mID, &retVal, aOk);
-  return retVal;
-}
-
-bool
-ProxyAccessible::IsLinkValid()
-{
-  bool retVal = false;
-  Unused << mDoc->SendIsLinkValid(mID, &retVal);
-  return retVal;
-}
-
-uint32_t
-ProxyAccessible::AnchorCount(bool* aOk)
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendAnchorCount(mID, &retVal, aOk);
-  return retVal;
-}
-
-void
-ProxyAccessible::AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk)
-{
-  Unused << mDoc->SendAnchorURIAt(mID, aIndex, &aURI, aOk);
-}
-
-ProxyAccessible*
-ProxyAccessible::AnchorAt(uint32_t aIndex)
-{
-  uint64_t id = 0;
-  bool ok = false;
-  Unused << mDoc->SendAnchorAt(mID, aIndex, &id, &ok);
-  return ok ? mDoc->GetAccessible(id) : nullptr;
-}
-
-uint32_t
-ProxyAccessible::LinkCount()
-{
-  uint32_t retVal = 0;
-  Unused << mDoc->SendLinkCount(mID, &retVal);
-  return retVal;
-}
-
-ProxyAccessible*
-ProxyAccessible::LinkAt(const uint32_t& aIndex)
-{
-  uint64_t linkID = 0;
-  bool ok = false;
-  Unused << mDoc->SendLinkAt(mID, aIndex, &linkID, &ok);
-  return ok ? mDoc->GetAccessible(linkID) : nullptr;
-}
-
-int32_t
-ProxyAccessible::LinkIndexOf(ProxyAccessible* aLink)
-{
-  int32_t retVal = -1;
-  if (aLink) {
-    Unused << mDoc->SendLinkIndexOf(mID, aLink->ID(), &retVal);
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return state;
   }
 
-  return retVal;
-}
-
-int32_t
-ProxyAccessible::LinkIndexAtOffset(uint32_t aOffset)
-{
-  int32_t retVal = -1;
-  Unused << mDoc->SendLinkIndexAtOffset(mID, aOffset, &retVal);
-  return retVal;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableOfACell()
-{
-  uint64_t tableID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableOfACell(mID, &tableID, &ok);
-  return ok ? mDoc->GetAccessible(tableID) : nullptr;
-}
-
-uint32_t
-ProxyAccessible::ColIdx()
-{
-  uint32_t index = 0;
-  Unused << mDoc->SendColIdx(mID, &index);
-  return index;
-}
-
-uint32_t
-ProxyAccessible::RowIdx()
-{
-  uint32_t index = 0;
-  Unused << mDoc->SendRowIdx(mID, &index);
-  return index;
-}
-
-uint32_t
-ProxyAccessible::ColExtent()
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendColExtent(mID, &extent);
-  return extent;
-}
-
-uint32_t
-ProxyAccessible::RowExtent()
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendRowExtent(mID, &extent);
-  return extent;
-}
-
-void
-ProxyAccessible::ColHeaderCells(nsTArray<ProxyAccessible*>* aCells)
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendColHeaderCells(mID, &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  for (size_t i = 0; i < targetCount; i++) {
-    aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
-  }
-}
-
-void
-ProxyAccessible::RowHeaderCells(nsTArray<ProxyAccessible*>* aCells)
-{
-  nsTArray<uint64_t> targetIDs;
-  Unused << mDoc->SendRowHeaderCells(mID, &targetIDs);
-
-  size_t targetCount = targetIDs.Length();
-  for (size_t i = 0; i < targetCount; i++) {
-    aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
-  }
-}
-
-bool
-ProxyAccessible::IsCellSelected()
-{
-  bool selected = false;
-  Unused << mDoc->SendIsCellSelected(mID, &selected);
-  return selected;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableCaption()
-{
-  uint64_t captionID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableCaption(mID, &captionID, &ok);
-  return ok ? mDoc->GetAccessible(captionID) : nullptr;
-}
-
-void
-ProxyAccessible::TableSummary(nsString& aSummary)
-{
-  Unused << mDoc->SendTableSummary(mID, &aSummary);
-}
-
-uint32_t
-ProxyAccessible::TableColumnCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableColumnCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableRowCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableRowCount(mID, &count);
-  return count;
-}
-
-ProxyAccessible*
-ProxyAccessible::TableCellAt(uint32_t aRow, uint32_t aCol)
-{
-  uint64_t cellID = 0;
-  bool ok = false;
-  Unused << mDoc->SendTableCellAt(mID, aRow, aCol, &cellID, &ok);
-  return ok ? mDoc->GetAccessible(cellID) : nullptr;
-}
-
-int32_t
-ProxyAccessible::TableCellIndexAt(uint32_t aRow, uint32_t aCol)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableCellIndexAt(mID, aRow, aCol, &index);
-  return index;
-}
-
-int32_t
-ProxyAccessible::TableColumnIndexAt(uint32_t aCellIndex)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableColumnIndexAt(mID, aCellIndex, &index);
-  return index;
-}
-
-int32_t
-ProxyAccessible::TableRowIndexAt(uint32_t aCellIndex)
-{
-  int32_t index = 0;
-  Unused << mDoc->SendTableRowIndexAt(mID, aCellIndex, &index);
-  return index;
-}
-
-void
-ProxyAccessible::TableRowAndColumnIndicesAt(uint32_t aCellIndex,
-                                            int32_t* aRow, int32_t* aCol)
-{
-  Unused << mDoc->SendTableRowAndColumnIndicesAt(mID, aCellIndex, aRow, aCol);
-}
-
-uint32_t
-ProxyAccessible::TableColumnExtentAt(uint32_t aRow, uint32_t aCol)
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendTableColumnExtentAt(mID, aRow, aCol, &extent);
-  return extent;
-}
-
-uint32_t
-ProxyAccessible::TableRowExtentAt(uint32_t aRow, uint32_t aCol)
-{
-  uint32_t extent = 0;
-  Unused << mDoc->SendTableRowExtentAt(mID, aRow, aCol, &extent);
-  return extent;
-}
-
-void
-ProxyAccessible::TableColumnDescription(uint32_t aCol, nsString& aDescription)
-{
-  Unused << mDoc->SendTableColumnDescription(mID, aCol, &aDescription);
-}
-
-void
-ProxyAccessible::TableRowDescription(uint32_t aRow, nsString& aDescription)
-{
-  Unused << mDoc->SendTableRowDescription(mID, aRow, &aDescription);
-}
-
-bool
-ProxyAccessible::TableColumnSelected(uint32_t aCol)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableColumnSelected(mID, aCol, &selected);
-  return selected;
-}
-
-bool
-ProxyAccessible::TableRowSelected(uint32_t aRow)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableRowSelected(mID, aRow, &selected);
-  return selected;
-}
-
-bool
-ProxyAccessible::TableCellSelected(uint32_t aRow, uint32_t aCol)
-{
-  bool selected = false;
-  Unused << mDoc->SendTableCellSelected(mID, aRow, aCol, &selected);
-  return selected;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedCellCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedCellCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedColumnCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedColumnCount(mID, &count);
-  return count;
-}
-
-uint32_t
-ProxyAccessible::TableSelectedRowCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendTableSelectedRowCount(mID, &count);
-  return count;
-}
-
-void
-ProxyAccessible::TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs)
-{
-  AutoTArray<uint64_t, 30> cellIDs;
-  Unused << mDoc->SendTableSelectedCells(mID, &cellIDs);
-  aCellIDs->SetCapacity(cellIDs.Length());
-  for (uint32_t i = 0; i < cellIDs.Length(); ++i) {
-    aCellIDs->AppendElement(mDoc->GetAccessible(cellIDs[i]));
+  VARIANT id;
+  id.vt = VT_I4;
+  id.lVal = CHILDID_SELF;
+  VARIANT varState;
+  HRESULT hr = acc->get_accState(id, &varState);
+  if (FAILED(hr)) {
+    return state;
   }
-}
-
-void
-ProxyAccessible::TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices)
-{
-  Unused << mDoc->SendTableSelectedCellIndices(mID, aCellIndices);
-}
-
-void
-ProxyAccessible::TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices)
-{
-  Unused << mDoc->SendTableSelectedColumnIndices(mID, aColumnIndices);
-}
-
-void
-ProxyAccessible::TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices)
-{
-  Unused << mDoc->SendTableSelectedRowIndices(mID, aRowIndices);
-}
-
-void
-ProxyAccessible::TableSelectColumn(uint32_t aCol)
-{
-  Unused << mDoc->SendTableSelectColumn(mID, aCol);
-}
-
-void
-ProxyAccessible::TableSelectRow(uint32_t aRow)
-{
-  Unused << mDoc->SendTableSelectRow(mID, aRow);
-}
-
-void
-ProxyAccessible::TableUnselectColumn(uint32_t aCol)
-{
-  Unused << mDoc->SendTableUnselectColumn(mID, aCol);
-}
-
-void
-ProxyAccessible::TableUnselectRow(uint32_t aRow)
-{
-  Unused << mDoc->SendTableUnselectRow(mID, aRow);
-}
-
-bool
-ProxyAccessible::TableIsProbablyForLayout()
-{
-  bool forLayout = false;
-  Unused << mDoc->SendTableIsProbablyForLayout(mID, &forLayout);
-  return forLayout;
-}
-
-ProxyAccessible*
-ProxyAccessible::AtkTableColumnHeader(int32_t aCol)
-{
-  uint64_t headerID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAtkTableColumnHeader(mID, aCol, &headerID, &ok);
-  return ok ? mDoc->GetAccessible(headerID) : nullptr;
-}
-
-ProxyAccessible*
-ProxyAccessible::AtkTableRowHeader(int32_t aRow)
-{
-  uint64_t headerID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAtkTableRowHeader(mID, aRow, &headerID, &ok);
-  return ok ? mDoc->GetAccessible(headerID) : nullptr;
-}
-
-void
-ProxyAccessible::SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems)
-{
-  AutoTArray<uint64_t, 10> itemIDs;
-  Unused << mDoc->SendSelectedItems(mID, &itemIDs);
-  aSelectedItems->SetCapacity(itemIDs.Length());
-  for (size_t i = 0; i < itemIDs.Length(); ++i) {
-    aSelectedItems->AppendElement(mDoc->GetAccessible(itemIDs[i]));
-  }
-}
-
-uint32_t
-ProxyAccessible::SelectedItemCount()
-{
-  uint32_t count = 0;
-  Unused << mDoc->SendSelectedItemCount(mID, &count);
-  return count;
-}
-
-ProxyAccessible*
-ProxyAccessible::GetSelectedItem(uint32_t aIndex)
-{
-  uint64_t selectedItemID = 0;
-  bool ok = false;
-  Unused << mDoc->SendGetSelectedItem(mID, aIndex, &selectedItemID, &ok);
-  return ok ? mDoc->GetAccessible(selectedItemID) : nullptr;
-}
-
-bool
-ProxyAccessible::IsItemSelected(uint32_t aIndex)
-{
-  bool selected = false;
-  Unused << mDoc->SendIsItemSelected(mID, aIndex, &selected);
-  return selected;
-}
- 
-bool
-ProxyAccessible::AddItemToSelection(uint32_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendAddItemToSelection(mID, aIndex, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::RemoveItemFromSelection(uint32_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendRemoveItemFromSelection(mID, aIndex, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::SelectAll()
-{
-  bool success = false;
-  Unused << mDoc->SendSelectAll(mID, &success);
-  return success;
-}
-
-bool
-ProxyAccessible::UnselectAll()
-{
-  bool success = false;
-  Unused << mDoc->SendUnselectAll(mID, &success);
-  return success;
-}
-
-void
-ProxyAccessible::TakeSelection()
-{
-  Unused << mDoc->SendTakeSelection(mID);
-}
-
-void
-ProxyAccessible::SetSelected(bool aSelect)
-{
-  Unused << mDoc->SendSetSelected(mID, aSelect);
-}
-
-bool
-ProxyAccessible::DoAction(uint8_t aIndex)
-{
-  bool success = false;
-  Unused << mDoc->SendDoAction(mID, aIndex, &success);
-  return success;
-}
-
-uint8_t
-ProxyAccessible::ActionCount()
-{
-  uint8_t count = 0;
-  Unused << mDoc->SendActionCount(mID, &count);
-  return count;
-}
-
-void
-ProxyAccessible::ActionDescriptionAt(uint8_t aIndex, nsString& aDescription)
-{
-  Unused << mDoc->SendActionDescriptionAt(mID, aIndex, &aDescription);
-}
-
-void
-ProxyAccessible::ActionNameAt(uint8_t aIndex, nsString& aName)
-{
-  Unused << mDoc->SendActionNameAt(mID, aIndex, &aName);
-}
-
-KeyBinding
-ProxyAccessible::AccessKey()
-{
-  uint32_t key = 0;
-  uint32_t modifierMask = 0;
-  Unused << mDoc->SendAccessKey(mID, &key, &modifierMask);
-  return KeyBinding(key, modifierMask);
-}
-
-KeyBinding
-ProxyAccessible::KeyboardShortcut()
-{
-  uint32_t key = 0;
-  uint32_t modifierMask = 0;
-  Unused << mDoc->SendKeyboardShortcut(mID, &key, &modifierMask);
-  return KeyBinding(key, modifierMask);
-}
-
-void
-ProxyAccessible::AtkKeyBinding(nsString& aBinding)
-{
-  Unused << mDoc->SendAtkKeyBinding(mID, &aBinding);
-}
-
-double
-ProxyAccessible::CurValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendCurValue(mID, &val);
-  return val;
-}
-
-bool
-ProxyAccessible::SetCurValue(double aValue)
-{
-  bool success = false;
-  Unused << mDoc->SendSetCurValue(mID, aValue, &success);
-  return success;
-}
-
-double
-ProxyAccessible::MinValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendMinValue(mID, &val);
-  return val;
-}
-
-double
-ProxyAccessible::MaxValue()
-{
-  double val = UnspecifiedNaN<double>();
-  Unused << mDoc->SendMaxValue(mID, &val);
-  return val;
-}
-
-double
-ProxyAccessible::Step()
-{
-  double step = UnspecifiedNaN<double>();
-  Unused << mDoc->SendStep(mID, &step);
-  return step;
-}
-
-void
-ProxyAccessible::TakeFocus()
-{
-  Unused << mDoc->SendTakeFocus(mID);
-}
-
-uint32_t
-ProxyAccessible::EmbeddedChildCount() const
-{
-  size_t count = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (mChildren[i]->IsEmbeddedObject()) {
-      count++;
-    }
-  }
-
-  return count;
-}
-
-int32_t
-ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
-{
-  size_t index = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (mChildren[i]->IsEmbeddedObject()) {
-      if (mChildren[i] == aChild) {
-        return index;
-      }
-
-      index++;
-    }
-  }
-
-  return -1;
-}
-
-ProxyAccessible*
-ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
-{
-  size_t index = 0, kids = mChildren.Length();
-  for (size_t i = 0; i < kids; i++) {
-    if (!mChildren[i]->IsEmbeddedObject()) {
-      continue;
-    }
-
-    if (index == aChildIdx) {
-      return mChildren[i];
-    }
-
-    index++;
-  }
-
-  return nullptr;
-}
-
-ProxyAccessible*
-ProxyAccessible::FocusedChild()
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused << mDoc->SendFocusedChild(mID, &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
-}
-
-ProxyAccessible*
-ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
-                              Accessible::EWhichChildAtPoint aWhichChild)
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused << mDoc->SendAccessibleAtPoint(mID, aX, aY, false,
-                                        static_cast<uint32_t>(aWhichChild),
-                                        &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
+  return uint64_t(varState.lVal);
 }
 
 nsIntRect
 ProxyAccessible::Bounds()
 {
   nsIntRect rect;
-  Unused << mDoc->SendExtents(mID, false,
-                              &(rect.x), &(rect.y),
-                              &(rect.width), &(rect.height));
+
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return rect;
+  }
+
+  long left;
+  long top;
+  long width;
+  long height;
+  VARIANT id;
+  id.vt = VT_I4;
+  id.lVal = CHILDID_SELF;
+  HRESULT hr = acc->accLocation(&left, &top, &width, &height, id);
+  if (FAILED(hr)) {
+    return rect;
+  }
+  rect.x = left;
+  rect.y = top;
+  rect.width = width;
+  rect.height = height;
   return rect;
 }
 
 void
 ProxyAccessible::Language(nsString& aLocale)
 {
-  Unused << mDoc->SendLanguage(mID, &aLocale);
+  aLocale.Truncate();
+
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return;
+  }
+
+  RefPtr<IAccessible2> acc2;
+  if (FAILED(acc->QueryInterface(IID_IAccessible2, (void**)getter_AddRefs(acc2)))) {
+    return;
+  }
+
+  IA2Locale locale;
+  HRESULT hr = acc2->get_locale(&locale);
+
+  _bstr_t langWrap(locale.language, false);
+  _bstr_t countryWrap(locale.country, false);
+  _bstr_t variantWrap(locale.variant, false);
+
+  if (FAILED(hr)) {
+    return;
+  }
+
+  // The remaining code should essentially be the inverse of the
+  // ia2Accessible::get_locale conversion to IA2Locale.
+
+  if (!!variantWrap) {
+    aLocale = (wchar_t*)variantWrap;
+    return;
+  }
+
+  if (!!langWrap) {
+    aLocale = (wchar_t*)langWrap;
+    if (!!countryWrap) {
+      aLocale += L"-";
+      aLocale += (wchar_t*)countryWrap;
+    }
+  }
 }
 
-void
-ProxyAccessible::DocType(nsString& aType)
+static bool
+IsEscapedChar(const wchar_t c)
 {
-  Unused << mDoc->SendDocType(mID, &aType);
+  return c == L'\\' || c == L':' || c == ',' || c == '=' || c == ';';
 }
 
-void
-ProxyAccessible::Title(nsString& aTitle)
+static bool
+ConvertBSTRAttributesToArray(const nsAString& aStr,
+                             nsTArray<Attribute>* aAttrs)
 {
-  Unused << mDoc->SendTitle(mID, &aTitle);
-}
+  if (!aAttrs) {
+    return false;
+  }
+
+  enum
+  {
+    eName = 0,
+    eValue = 1,
+    eNumStates
+  } state;
+  nsAutoString tokens[eNumStates];
+  auto itr = aStr.BeginReading(), end = aStr.EndReading();
 
-void
-ProxyAccessible::URL(nsString& aURL)
-{
-  Unused << mDoc->SendURL(mID, &aURL);
-}
-
-void
-ProxyAccessible::MimeType(nsString aMime)
-{
-  Unused << mDoc->SendMimeType(mID, &aMime);
+  state = eName;
+  while (itr != end) {
+    switch (*itr) {
+      case L'\\':
+        // Skip the backslash so that we're looking at the escaped char
+        ++itr;
+        if (itr == end || !IsEscapedChar(*itr)) {
+          // Invalid state
+          return false;
+        }
+        break;
+      case L':':
+        if (state != eName) {
+          // Bad, should be looking at name
+          return false;
+        }
+        state = eValue;
+        ++itr;
+        continue;
+      case L';':
+        if (state != eValue) {
+          // Bad, should be looking at value
+          return false;
+        }
+        state = eName;
+        aAttrs->AppendElement(Attribute(NS_ConvertUTF16toUTF8(tokens[eName]),
+                                        tokens[eValue]));
+        tokens[eName].Truncate();
+        tokens[eValue].Truncate();
+        ++itr;
+        continue;
+      default:
+        break;
+    }
+    tokens[state] += *itr;
+  }
+  return true;
 }
 
 void
-ProxyAccessible::URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
-                                    nsString& aMimeType)
+ProxyAccessible::Attributes(nsTArray<Attribute>* aAttrs) const
 {
-  Unused << mDoc->SendURLDocTypeMimeType(mID, &aURL, &aDocType, &aMimeType);
-}
+  aAttrs->Clear();
+
+  RefPtr<IAccessible> acc;
+  if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
+    return;
+  }
 
-ProxyAccessible*
-ProxyAccessible::AccessibleAtPoint(int32_t aX, int32_t aY,
-                                   bool aNeedsScreenCoords)
-{
-  uint64_t childID = 0;
-  bool ok = false;
-  Unused <<
-    mDoc->SendAccessibleAtPoint(mID, aX, aY, aNeedsScreenCoords,
-                                static_cast<uint32_t>(Accessible::eDirectChild),
-                                &childID, &ok);
-  return ok ? mDoc->GetAccessible(childID) : nullptr;
+  RefPtr<IAccessible2> acc2;
+  if (FAILED(acc->QueryInterface(IID_IAccessible2, (void**)getter_AddRefs(acc2)))) {
+    return;
+  }
+
+  BSTR attrs;
+  HRESULT hr = acc2->get_attributes(&attrs);
+  _bstr_t attrsWrap(attrs, false);
+  if (FAILED(hr)) {
+    return;
+  }
+
+  ConvertBSTRAttributesToArray(nsDependentString((wchar_t*)attrs,
+                                                 attrsWrap.length()),
+                               aAttrs);
 }
 
-void
-ProxyAccessible::Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY,
-                        int32_t* aWidth, int32_t* aHeight)
-{
-  Unused << mDoc->SendExtents(mID, aNeedsScreenCoords, aX, aY, aWidth, aHeight);
-}
-
-void
-ProxyAccessible::DOMNodeID(nsString& aID)
-{
-  Unused << mDoc->SendDOMNodeID(mID, &aID);
-}
-
-Accessible*
-ProxyAccessible::OuterDocOfRemoteBrowser() const
-{
-  auto tab = static_cast<dom::TabParent*>(mDoc->Manager());
-  dom::Element* frame = tab->GetOwnerElement();
-  NS_ASSERTION(frame, "why isn't the tab in a frame!");
-  if (!frame)
-    return nullptr;
-
-  DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
-
-  return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
-}
-}
-}
+} // namespace a11y
+} // namespace mozilla
copy from accessible/ipc/ProxyAccessible.h
copy to accessible/ipc/win/ProxyAccessible.h
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/win/ProxyAccessible.h
@@ -2,453 +2,87 @@
 /* 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/. */
 
 #ifndef mozilla_a11y_ProxyAccessible_h
 #define mozilla_a11y_ProxyAccessible_h
 
+#include "Accessible.h"
+#include "mozilla/a11y/ProxyAccessibleBase.h"
 #include "mozilla/a11y/Role.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleTypes.h"
-#include "Accessible.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRect.h"
-#include "Accessible.h"
+
+#include <oleacc.h>
 
 namespace mozilla {
 namespace a11y {
 
-class Accessible;
-class Attribute;
-class DocAccessibleParent;
-enum class RelationType;
-
-enum Interfaces
-{
-  HYPERTEXT = 1,
-  HYPERLINK = 1 << 1,
-  IMAGE = 1 << 2,
-  VALUE = 1 << 3,
-  TABLE = 1 << 4,
-  TABLECELL = 1 << 5,
-  DOCUMENT = 1 << 6,
-  SELECTION = 1 << 7,
-  ACTION = 1 << 8,
-};
-
-class ProxyAccessible
+class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible>
 {
 public:
+  ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
+                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces,
+                  const RefPtr<IAccessible>& aIAccessible)
+    : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
+    , mCOMProxy(aIAccessible)
 
-  ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
-                  DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) :
-     mParent(aParent), mDoc(aDoc), mWrapper(0), mID(aID), mRole(aRole),
-     mOuterDoc(false), mIsDoc(false),
-     mHasValue(aInterfaces & Interfaces::VALUE),
-     mIsHyperLink(aInterfaces & Interfaces::HYPERLINK),
-     mIsHyperText(aInterfaces & Interfaces::HYPERTEXT)
   {
     MOZ_COUNT_CTOR(ProxyAccessible);
   }
+
   ~ProxyAccessible()
   {
     MOZ_COUNT_DTOR(ProxyAccessible);
-    MOZ_ASSERT(!mWrapper);
-  }
-
-  void AddChildAt(uint32_t aIdx, ProxyAccessible* aChild)
-  { mChildren.InsertElementAt(aIdx, aChild); }
-
-  uint32_t ChildrenCount() const { return mChildren.Length(); }
-  ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
-  ProxyAccessible* FirstChild() const
-    { return mChildren.Length() ? mChildren[0] : nullptr; }
-  ProxyAccessible* LastChild() const
-    { return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; }
-  ProxyAccessible* PrevSibling() const
-  {
-    size_t idx = IndexInParent();
-    return idx > 0 ? Parent()->mChildren[idx - 1] : nullptr;
-  }
-  ProxyAccessible* NextSibling() const
-  {
-    size_t idx = IndexInParent();
-    return idx + 1 < Parent()->mChildren.Length() ? Parent()->mChildren[idx + 1]
-    : nullptr;
-  }
-
-  // XXX evaluate if this is fast enough.
-  size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
-  uint32_t EmbeddedChildCount() const;
-  int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
-  ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
-  bool MustPruneChildren() const;
-
-  void Shutdown();
-
-  void SetChildDoc(DocAccessibleParent*);
-
-  /**
-   * Remove The given child.
-   */
-  void RemoveChild(ProxyAccessible* aChild)
-    { mChildren.RemoveElement(aChild); }
-
-  /**
-   * Return the proxy for the parent of the wrapped accessible.
-   */
-  ProxyAccessible* Parent() const { return mParent; }
-
-  Accessible* OuterDocOfRemoteBrowser() const;
-
-  /**
-   * Get the role of the accessible we're proxying.
-   */
-  role Role() const { return mRole; }
-
-  /**
-   * Return true if this is an embedded object.
-   */
-  bool IsEmbeddedObject() const
-  {
-    role role = Role();
-    return role != roles::TEXT_LEAF &&
-           role != roles::WHITESPACE &&
-           role != roles::STATICTEXT;
   }
 
   /*
    * Return the states for the proxied accessible.
    */
   uint64_t State() const;
 
   /*
-   * Return the native states for the proxied accessible.
-   */
-  uint64_t NativeState() const;
-
-  /*
    * Set aName to the name of the proxied accessible.
    */
   void Name(nsString& aName) const;
 
   /*
    * Set aValue to the value of the proxied accessible.
    */
   void Value(nsString& aValue) const;
 
-  /*
-   * Set aHelp to the help string of the proxied accessible.
-   */
-  void Help(nsString& aHelp) const;
-
   /**
    * Set aDesc to the description of the proxied accessible.
    */
   void Description(nsString& aDesc) const;
 
   /**
    * Get the set of attributes on the proxied accessible.
    */
   void Attributes(nsTArray<Attribute> *aAttrs) const;
 
-  /**
-   * Return set of targets of given relation type.
-   */
-  nsTArray<ProxyAccessible*> RelationByType(RelationType aType) const;
-
-  /**
-   * Get all relations for this accessible.
-   */
-  void Relations(nsTArray<RelationType>* aTypes,
-                 nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) const;
-
-  bool IsSearchbox() const;
-
-  nsIAtom* LandmarkRole() const;
-
-  nsIAtom* ARIARoleAtom() const;
-
-  int32_t GetLevelInternal();
-  void ScrollTo(uint32_t aScrollType);
-  void ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY);
-
-  int32_t CaretLineNumber();
-  int32_t CaretOffset();
-  void SetCaretOffset(int32_t aOffset);
-
-  int32_t CharacterCount();
-  int32_t SelectionCount();
-
-  /**
-   * Get the text between the given offsets.
-   */
-  bool TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
-                     nsString& aText) const;
-
-  void GetTextAfterOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                          nsString& aText, int32_t* aStartOffset,
-                          int32_t* aEndOffset);
-
-  void GetTextAtOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                       nsString& aText, int32_t* aStartOffset,
-                       int32_t* aEndOffset);
-
-  void GetTextBeforeOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
-                           nsString& aText, int32_t* aStartOffset,
-                           int32_t* aEndOffset);
-
-  char16_t CharAt(int32_t aOffset);
-
-  void TextAttributes(bool aIncludeDefAttrs,
-                      const int32_t aOffset,
-                      nsTArray<Attribute>* aAttributes,
-                      int32_t* aStartOffset,
-                      int32_t* aEndOffset);
-  void DefaultTextAttributes(nsTArray<Attribute>* aAttrs);
-
-  nsIntRect TextBounds(int32_t aStartOffset, int32_t aEndOffset,
-                       uint32_t aCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE);
-
-  nsIntRect CharBounds(int32_t aOffset, uint32_t aCoordType);
-
-  int32_t OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType);
-
-  bool SelectionBoundsAt(int32_t aSelectionNum,
-                         nsString& aData,
-                         int32_t* aStartOffset,
-                         int32_t* aEndOffset);
-
-  bool SetSelectionBoundsAt(int32_t aSelectionNum,
-                            int32_t aStartOffset,
-                            int32_t aEndOffset);
-
-  bool AddToSelection(int32_t aStartOffset,
-                      int32_t aEndOffset);
-
-  bool RemoveFromSelection(int32_t aSelectionNum);
-
-  void ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset,
-                         uint32_t aScrollType);
-
-  void ScrollSubstringToPoint(int32_t aStartOffset,
-                              int32_t aEndOffset,
-                              uint32_t aCoordinateType,
-                              int32_t aX, int32_t aY);
-
-  void Text(nsString* aText);
-
-  void ReplaceText(const nsString& aText);
-
-  bool InsertText(const nsString& aText, int32_t aPosition);
-
-  bool CopyText(int32_t aStartPos, int32_t aEndPos);
-
-  bool CutText(int32_t aStartPos, int32_t aEndPos);
-
-  bool DeleteText(int32_t aStartPos, int32_t aEndPos);
-
-  bool PasteText(int32_t aPosition);
-
-  nsIntPoint ImagePosition(uint32_t aCoordType);
-
-  nsIntSize ImageSize();
-
-  uint32_t StartOffset(bool* aOk);
-
-  uint32_t EndOffset(bool* aOk);
-
-  bool IsLinkValid();
-
-  // XXX checking mRole alone may not result in same behavior as Accessibles
-  // due to ARIA roles. See bug 1210477.
-  inline bool IsTable() const
-  {
-    return mRole == roles::TABLE || mRole == roles::MATHML_TABLE;
-  }
-  inline bool IsTableRow() const
-  {
-    return (mRole == roles::ROW ||
-            mRole == roles::MATHML_TABLE_ROW ||
-            mRole == roles::MATHML_LABELED_ROW);
-  }
-  inline bool IsTableCell() const
-  {
-    return (mRole == roles::CELL ||
-            mRole == roles::COLUMNHEADER ||
-            mRole == roles::ROWHEADER ||
-            mRole == roles::GRID_CELL ||
-            mRole == roles::MATHML_CELL);
-  }
-
-  uint32_t AnchorCount(bool* aOk);
-
-  void AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk);
-
-  ProxyAccessible* AnchorAt(uint32_t aIndex);
-
-  uint32_t LinkCount();
-
-  ProxyAccessible* LinkAt(const uint32_t& aIndex);
-
-  int32_t LinkIndexOf(ProxyAccessible* aLink);
-
-  int32_t LinkIndexAtOffset(uint32_t aOffset);
-
-  ProxyAccessible* TableOfACell();
-
-  uint32_t ColIdx();
-
-  uint32_t RowIdx();
-
-  uint32_t ColExtent();
-
-  uint32_t RowExtent();
-
-  void ColHeaderCells(nsTArray<ProxyAccessible*>* aCells);
-
-  void RowHeaderCells(nsTArray<ProxyAccessible*>* aCells);
-
-  bool IsCellSelected();
-
-  ProxyAccessible* TableCaption();
-  void TableSummary(nsString& aSummary);
-  uint32_t TableColumnCount();
-  uint32_t TableRowCount();
-  ProxyAccessible* TableCellAt(uint32_t aRow, uint32_t aCol);
-  int32_t TableCellIndexAt(uint32_t aRow, uint32_t aCol);
-  int32_t TableColumnIndexAt(uint32_t aCellIndex);
-  int32_t TableRowIndexAt(uint32_t aCellIndex);
-  void TableRowAndColumnIndicesAt(uint32_t aCellIndex,
-                                  int32_t* aRow, int32_t* aCol);
-  uint32_t TableColumnExtentAt(uint32_t aRow, uint32_t aCol);
-  uint32_t TableRowExtentAt(uint32_t aRow, uint32_t aCol);
-  void TableColumnDescription(uint32_t aCol, nsString& aDescription);
-  void TableRowDescription(uint32_t aRow, nsString& aDescription);
-  bool TableColumnSelected(uint32_t aCol);
-  bool TableRowSelected(uint32_t aRow);
-  bool TableCellSelected(uint32_t aRow, uint32_t aCol);
-  uint32_t TableSelectedCellCount();
-  uint32_t TableSelectedColumnCount();
-  uint32_t TableSelectedRowCount();
-  void TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs);
-  void TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices);
-  void TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices);
-  void TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices);
-  void TableSelectColumn(uint32_t aCol);
-  void TableSelectRow(uint32_t aRow);
-  void TableUnselectColumn(uint32_t aCol);
-  void TableUnselectRow(uint32_t aRow);
-  bool TableIsProbablyForLayout();
-  ProxyAccessible* AtkTableColumnHeader(int32_t aCol);
-  ProxyAccessible* AtkTableRowHeader(int32_t aRow);
-
-  void SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems);
-  uint32_t SelectedItemCount();
-  ProxyAccessible* GetSelectedItem(uint32_t aIndex);
-  bool IsItemSelected(uint32_t aIndex);
-  bool AddItemToSelection(uint32_t aIndex);
-  bool RemoveItemFromSelection(uint32_t aIndex);
-  bool SelectAll();
-  bool UnselectAll();
-
-  void TakeSelection();
-  void SetSelected(bool aSelect);
-
-  bool DoAction(uint8_t aIndex);
-  uint8_t ActionCount();
-  void ActionDescriptionAt(uint8_t aIndex, nsString& aDescription);
-  void ActionNameAt(uint8_t aIndex, nsString& aName);
-  KeyBinding AccessKey();
-  KeyBinding KeyboardShortcut();
-  void AtkKeyBinding(nsString& aBinding);
-
-  double CurValue();
-  bool SetCurValue(double aValue);
-  double MinValue();
-  double MaxValue();
-  double Step();
-
-  void TakeFocus();
-  ProxyAccessible* FocusedChild();
-  ProxyAccessible* ChildAtPoint(int32_t aX, int32_t aY,
-                                Accessible::EWhichChildAtPoint aWhichChild);
   nsIntRect Bounds();
 
   void Language(nsString& aLocale);
-  void DocType(nsString& aType);
-  void Title(nsString& aTitle);
-  void URL(nsString& aURL);
-  void MimeType(nsString aMime);
-  void URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
-                          nsString& aMimeType);
 
-  ProxyAccessible* AccessibleAtPoint(int32_t aX, int32_t aY,
-                                     bool aNeedsScreenCoords);
-
-  void Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY,
-               int32_t* aWidth, int32_t* aHeight);
-
-  /**
-   * Return the id of the dom node this accessible represents.  Note this
-   * should probably only be used for testing.
-   */
-  void DOMNodeID(nsString& aID);
-
-  /**
-   * Allow the platform to store a pointers worth of data on us.
-   */
-  uintptr_t GetWrapper() const { return mWrapper; }
-  void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
-
-  /*
-   * Return the ID of the accessible being proxied.
-   */
-  uint64_t ID() const { return mID; }
-
-  /**
-   * Return the document containing this proxy, or the proxy itself if it is a
-   * document.
-   */
-  DocAccessibleParent* Document() const { return mDoc; }
-
-  /**
-   * Return true if this proxy is a DocAccessibleParent.
-   */
-  bool IsDoc() const { return mIsDoc; }
-  DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; }
+  bool GetCOMInterface(void** aOutAccessible) const;
 
 protected:
-  explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) :
-    mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0),
-    mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
-    mIsHyperLink(false), mIsHyperText(false)
-  { MOZ_COUNT_CTOR(ProxyAccessible); }
+  explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
+    : ProxyAccessibleBase(aThisAsDoc)
+  { MOZ_COUNT_CTOR(ProxyAccessibleBase); }
 
-protected:
-  ProxyAccessible* mParent;
+  void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible)
+  { mCOMProxy = aIAccessible; }
 
 private:
-  nsTArray<ProxyAccessible*> mChildren;
-  DocAccessibleParent* mDoc;
-  uintptr_t mWrapper;
-  uint64_t mID;
-protected:
-  // XXX DocAccessibleParent gets to change this to change the role of
-  // documents.
-  role mRole : 27;
-private:
-  bool mOuterDoc : 1;
-
-public:
-  const bool mIsDoc: 1;
-  const bool mHasValue: 1;
-  const bool mIsHyperLink: 1;
-  const bool mIsHyperText: 1;
+  RefPtr<IAccessible> mCOMProxy;
 };
 
 }
 }
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/moz.build
@@ -0,0 +1,38 @@
+# -*- Mode: python; c-basic-offset: 4; 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/.
+
+DIRS += ['typelib']
+
+# With --disable-accessibility, we need to compile PDocAccessible.ipdl (which
+# also depends on COMPtrTypes.h), but not the C++.
+IPDL_SOURCES += ['PDocAccessible.ipdl']
+EXPORTS.mozilla.a11y += ['COMPtrTypes.h']
+
+if CONFIG['ACCESSIBILITY']:
+    EXPORTS.mozilla.a11y += [
+        'DocAccessibleChild.h',
+        'PlatformChild.h',
+        'ProxyAccessible.h'
+    ]
+
+    SOURCES += [
+        'COMPtrTypes.cpp',
+        'DocAccessibleChild.cpp',
+        'PlatformChild.cpp',
+        'ProxyAccessible.cpp',
+    ]
+
+    LOCAL_INCLUDES += [
+        '/accessible/base',
+        '/accessible/generic',
+        '/accessible/windows/ia2',
+        '/accessible/windows/msaa',
+        '/accessible/xpcom',
+    ]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/typelib/Accessible.idl
@@ -0,0 +1,16 @@
+/* -*- 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/. */
+
+import "oaidl.idl";
+import "servprov.idl";
+
+[uuid(b4d37cda-0dac-45e6-b613-158a5eb94293)]
+library Accessible
+{
+  interface IEnumVARIANT;
+  interface IServiceProvider;
+};
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/typelib/Makefile.in
@@ -0,0 +1,31 @@
+# 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
+
+MIDL_GENERATED_FILES = \
+  Accessible.h \
+  Accessible_i.c \
+  Accessible_p.c \
+  Accessible.tlb \
+  $(NULL)
+
+$(MIDL_GENERATED_FILES): done_gen
+
+done_gen: Accessible.idl
+	$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/Accessible.idl
+	touch $@
+
+export:: done_gen
+
+midl_exports := \
+  Accessible.tlb \
+  $(NULL)
+
+INSTALL_TARGETS += midl_exports
+midl_exports_FILES := $(midl_exports)
+midl_exports_DEST = $(DIST)/bin
+midl_exports_TARGET := export
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/typelib/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; c-basic-offset: 4; 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/.
+
+FINAL_TARGET_FILES += [
+    '!Accessible.tlb',
+]
+
+GENERATED_FILES += [
+    'Accessible.tlb',
+]
--- a/accessible/mac/moz.build
+++ b/accessible/mac/moz.build
@@ -27,16 +27,17 @@ UNIFIED_SOURCES += [
     'RootAccessibleWrap.mm',
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/ipc',
+    '/accessible/ipc/other',
     '/accessible/xul',
     '/layout/generic',
     '/layout/xul',
     '/widget',
     '/widget/cocoa',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/accessible/tests/mochitest/attributes/test_xml-roles.html
+++ b/accessible/tests/mochitest/attributes/test_xml-roles.html
@@ -26,16 +26,17 @@
       testAbsentAttrs("section_header", {"xml-roles" : "banner"});
       testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
       testAbsentAttrs("article_footer", {"xml-roles" : "contentinfo"});
       testAbsentAttrs("section_footer", {"xml-roles" : "contentinfo"});
       testAttrs("aside", {"xml-roles" : "complementary"}, true);
       testAttrs("section", {"xml-roles" : "region"}, true);
       testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
       testAttrs("form", {"xml-roles" : "form"}, true);
+      testAttrs("feed", {"xml-roles" : "feed"}, true);
       testAttrs("article", {"xml-roles" : "article"}, true);
       testAttrs("main_element", {"xml-roles" : "main"}, true);
 
       testAttrs("search", {"xml-roles" : "searchbox"}, true);
 
       testAttrs("open-1", {"xml-roles" : "open-fence"}, true);
       testAttrs("open-2", {"xml-roles" : "open-fence"}, true);
       testAttrs("open-3", {"xml-roles" : "open-fence"}, true);
@@ -154,16 +155,17 @@
   <section id="section_with_header_and_footer">
     <header id="section_header">a header within an section</header>
     <footer id="section_footer">a footer within an section</footer>
   </section>
   <aside id="aside">by the way I am an aside</aside>
   <section id="section">a section</section>
   <article id="main" role="main">a main area</article>
   <article id="form" role="form">a form area</article>
+  <div id="feed" role="feed">a feed</div>
   <article id="article">article</article>
   <main id="main_element">another main area</main>
 
   <input id="search" type="search"/>
 
   <!-- open-fence, separator, close-fence -->
   <math><mo id="open-1">(</mo><mi>x</mi><mo id="sep-1">,</mo><mi>y</mi><mo id="close-1">)</mo></math>
   <math><mrow><mo id="open-2">(</mo><mi>x</mi><mo id="sep-2">,</mo><mi>y</mi><mo id="close-2">)</mo></mrow></math>
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -315,17 +315,20 @@
     function removeGrandChildrenNHideParent(aChild1Id, aChild2Id, aParentId)
     {
       this.child1 = getNode(aChild1Id);
       this.child2 = getNode(aChild2Id);
       this.parent = getNode(aParentId);
 
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getAccessible(aParentId)),
-        new invokerChecker(EVENT_REORDER, getNode(aParentId).parentNode)
+        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.parent.hidden = true;
       }
--- a/accessible/tests/mochitest/jsat/a11y.ini
+++ b/accessible/tests/mochitest/jsat/a11y.ini
@@ -4,16 +4,17 @@ support-files =
   gestures.json
   jsatcommon.js
   output.js
   doc_traversal.html
   doc_content_integration.html
   doc_content_text.html
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/moz.png
+skip-if = os == 'win'
 
 [test_alive.html]
 [test_content_integration.html]
 skip-if = buildapp == 'mulet'
 [test_content_text.html]
 skip-if = buildapp == 'mulet'
 [test_explicit_names.html]
 [test_gesture_tracker.html]
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -25,16 +25,17 @@
       testRole("aria_button", ROLE_PUSHBUTTON);
       testRole("aria_checkbox", ROLE_CHECKBUTTON);
       testRole("aria_columnheader", ROLE_COLUMNHEADER);
       testRole("aria_combobox", ROLE_COMBOBOX);
       testRole("aria_dialog", ROLE_DIALOG);
       testRole("aria_directory", ROLE_LIST);
       testRole("aria_document", ROLE_DOCUMENT);
       testRole("aria_form", ROLE_FORM);
+      testRole("aria_feed", ROLE_GROUPING);
       testRole("aria_grid", ROLE_TABLE);
       testRole("aria_gridcell", ROLE_GRID_CELL);
       testRole("aria_group", ROLE_GROUPING);
       testRole("aria_heading", ROLE_HEADING);
       testRole("aria_img", ROLE_GRAPHIC);
       testRole("aria_link", ROLE_LINK);
       testRole("aria_list", ROLE_LIST);
       testRole("aria_listbox", ROLE_LISTBOX);
@@ -202,16 +203,17 @@
   <span id="aria_button" role="button"/>
   <span id="aria_checkbox" role="checkbox"/>
   <span id="aria_columnheader" role="columnheader"/>
   <span id="aria_combobox" role="combobox"/>
   <span id="aria_dialog" role="dialog"/>
   <span id="aria_directory" role="directory"/>
   <span id="aria_document" role="document"/>
   <span id="aria_form" role="form"/>
+  <span id="aria_feed" role="feed"/>
   <span id="aria_grid" role="grid"/>
   <span id="aria_gridcell" role="gridcell"/>
   <span id="aria_group" role="group"/>
   <span id="aria_heading" role="heading"/>
   <span id="aria_img" role="img"/>
   <span id="aria_link" role="link"/>
   <span id="aria_list" role="list"/>
   <span id="aria_listbox" role="listbox"/>
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -2,16 +2,18 @@
 <html>
 <head>
   <title>HTML input states</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="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
@@ -68,45 +70,56 @@
     ////////////////////////////////////////////////////////////////////////////
     // inherited from file control
     var fileBrowseButton = getAccessible("file").firstChild;
     testStates(fileBrowseButton, STATE_UNAVAILABLE | STATE_REQUIRED);
     // No states on the label.
 
     ////////////////////////////////////////////////////////////////////////////
     // 'invalid' state
-
-    // XXX: maxlength doesn't make the element invalid until bug 613016 and
-    // bug 613019 are fixed. Commenting out related lines and adding a todo to
-    // make sure it will be uncommented as soon as possible.
-    var todoInput = document.createElement("input");
-    todoInput.maxLength = '2';
-    todoInput.value = 'foo';
-    todo(!todoInput.validity.valid,
-         "input should be invalid because of maxlength");
-
-    // invalid/valid state
-    //var invalid = ["maxlength","pattern","email","url"];
-    //document.getElementById("maxlength").value = "i am too long";
     var invalid = ["pattern","email","url"];
     for (i in invalid) {
       testStates(invalid[i], STATE_INVALID);
       testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
     }
 
-    // invalid/valid state
-    //var invalid = ["maxlength","pattern","email","url"];
-    //document.getElementById("maxlength").value = "i am too long";
-    var invalid = ["pattern","email","url"];
-    for (i in invalid) {
-      testStates(invalid[i], STATE_INVALID);
-      testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
+    ////////////////////////////////////////////////////////////////////////////
+    // not 'invalid' state
+    // (per spec, min/maxlength are always valid until interactively edited)
+    var validInput = document.createElement("input");
+    validInput.maxLength = '0';
+    validInput.value = 'a';
+    ok(validInput.validity.valid,
+       "input should be valid despite maxlength (no interactive edits)");
+
+    var validInput2 = document.createElement("input");
+    validInput2.minLength = '1';
+    validInput2.value = '';
+    ok(validInput2.validity.valid,
+       "input should be valid despite minlength (no interactive edits)");
+
+    var valid = ["minlength","maxlength"];
+    for (i in valid) {
+      testStates(valid[i], 0, 0, STATE_INVALID);
+      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();
+    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.
+
+    ////////////////////////////////////////////////////////////////////////////
     // autocomplete states
     testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-formoff", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list2", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-tel", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-email", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
@@ -209,28 +222,20 @@
     <input id="f_input">
     <input id="f_input_disabled" disabled>
   </fieldset>
 
   <!-- inherited from input@type="file" -->
   <input id="file" type="file" required disabled>
 
   <!-- invalid/valid -->
-  <input id="maxlength" maxlength="1">
+  <input id="maxlength" maxlength="1" value="f">
   <input id="maxlength2" maxlength="100" value="foo">
-  <input id="pattern" pattern="bar" value="foo">
-  <input id="pattern2" pattern="bar" value="bar">
-  <input id="email" type="email" value="foo">
-  <input id="email2" type="email" value="foo@bar.com">
-  <input id="url" type="url" value="foo">
-  <input id="url2" type="url" value="http://mozilla.org/">
-
-  <!-- invalid/valid -->
-  <input id="maxlength" maxlength="1">
-  <input id="maxlength2" maxlength="100" value="foo">
+  <input id="minlength" minlength="2" value="fo">
+  <input id="minlength2" minlength="1" value="foo">
   <input id="pattern" pattern="bar" value="foo">
   <input id="pattern2" pattern="bar" value="bar">
   <input id="email" type="email" value="foo">
   <input id="email2" type="email" value="foo@bar.com">
   <input id="url" type="url" value="foo">
   <input id="url2" type="url" value="http://mozilla.org/">
 
   <!-- autocomplete -->
--- a/accessible/tests/mochitest/treeupdate/test_general.html
+++ b/accessible/tests/mochitest/treeupdate/test_general.html
@@ -77,30 +77,61 @@
       }
 
       this.getID = function removeRemove_getID()
       {
         return "remove first and second children";
       }
     }
 
+    function insertInaccessibleAccessibleSiblings()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, "c3")
+      ];
+
+      this.invoke = function insertInaccessibleAccessibleSiblings_invoke()
+      {
+        getNode("c3").appendChild(document.createElement("span"));
+        getNode("c3").appendChild(document.createElement("input"));
+      }
+
+      this.finalCheck = function insertInaccessibleAccessibleSiblings_finalCheck()
+      {
+        var accTree =
+          { SECTION: [ // container
+            { PUSHBUTTON: [
+              { TEXT_LEAF: [] }
+            ] },
+            { ENTRY: [ ] }
+          ] };
+        testAccessibleTree("c3", accTree);
+      }
+
+      this.getID = function insertInaccessibleAccessibleSiblings_getID()
+      {
+        return "insert inaccessible and then accessible siblings";
+      }
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // Do tests
     ////////////////////////////////////////////////////////////////////////////
 
     var gQueue = null;
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true;
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new prependAppend("c1"));
       gQueue.push(new removeRemove("c2"));
+      gQueue.push(new insertInaccessibleAccessibleSiblings());
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -108,10 +139,12 @@
 <body>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="c1"><input></div>
   <div id="c2"><span><input type="checkbox"><input></span><input type="button"></div>
+
+  <div id="c3"><input type="button" value="button"></div>
 </body>
 </html>
--- a/accessible/windows/ProxyWrappers.h
+++ b/accessible/windows/ProxyWrappers.h
@@ -10,45 +10,55 @@
 
 #include "HyperTextAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 class ProxyAccessibleWrap : public AccessibleWrap
 {
-  public:
+public:
   ProxyAccessibleWrap(ProxyAccessible* aProxy) :
     AccessibleWrap(nullptr, nullptr)
   {
     mType = eProxyType;
     mBits.proxy = aProxy;
   }
 
   virtual void Shutdown() override
   {
     mBits.proxy = nullptr;
     mStateFlags |= eIsDefunct;
   }
+
+  virtual void GetNativeInterface(void** aOutAccessible) override
+  {
+    mBits.proxy->GetCOMInterface(aOutAccessible);
+  }
 };
 
 class HyperTextProxyAccessibleWrap : public HyperTextAccessibleWrap
 {
 public:
   HyperTextProxyAccessibleWrap(ProxyAccessible* aProxy) :
     HyperTextAccessibleWrap(nullptr, nullptr)
   {
     mType = eProxyType;
     mBits.proxy = aProxy;
   }
 
   virtual void Shutdown() override
   {
     mBits.proxy = nullptr;
- mStateFlags |= eIsDefunct;
+    mStateFlags |= eIsDefunct;
+  }
+
+  virtual void GetNativeInterface(void** aOutAccessible) override
+  {
+    mBits.proxy->GetCOMInterface(aOutAccessible);
   }
 };
 
 class DocProxyAccessibleWrap : public HyperTextProxyAccessibleWrap
 {
 public:
   DocProxyAccessibleWrap(ProxyAccessible* aProxy) :
     HyperTextProxyAccessibleWrap(aProxy)
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -68,24 +68,17 @@ ia2Accessible::get_nRelations(long* aNRe
   if (!aNRelations)
     return E_INVALIDARG;
   *aNRelations = 0;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  if (acc->IsProxy()) {
-    // XXX evaluate performance of collecting all relation targets.
-    nsTArray<RelationType> types;
-    nsTArray<nsTArray<ProxyAccessible*>> targetSets;
-    acc->Proxy()->Relations(&types, &targetSets);
-    *aNRelations = types.Length();
-    return S_OK;
-  }
+  MOZ_ASSERT(!acc->IsProxy());
 
   for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
     if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
       continue;
 
     Relation rel = acc->RelationByType(sRelationTypePairs[idx].first);
     if (rel.Next())
       (*aNRelations)++;
@@ -104,43 +97,17 @@ ia2Accessible::get_relation(long aRelati
   if (!aRelation || aRelationIndex < 0)
     return E_INVALIDARG;
   *aRelation = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  if (acc->IsProxy()) {
-    nsTArray<RelationType> types;
-    nsTArray<nsTArray<ProxyAccessible*>> targetSets;
-    acc->Proxy()->Relations(&types, &targetSets);
-
-    size_t targetSetCount = targetSets.Length();
-    for (size_t i = 0; i < targetSetCount; i++) {
-      uint32_t relTypeIdx = static_cast<uint32_t>(types[i]);
-      MOZ_ASSERT(sRelationTypePairs[relTypeIdx].first == types[i]);
-      if (sRelationTypePairs[relTypeIdx].second == IA2_RELATION_NULL)
-        continue;
-
-      if (static_cast<size_t>(aRelationIndex) == i) {
-        nsTArray<RefPtr<Accessible>> targets;
-        size_t targetCount = targetSets[i].Length();
-        for (size_t j = 0; j < targetCount; j++)
-          targets.AppendElement(WrapperFor(targetSets[i][j]));
-
-        RefPtr<ia2AccessibleRelation> rel =
-          new ia2AccessibleRelation(types[i], Move(targets));
-        rel.forget(aRelation);
-        return S_OK;
-      }
-    }
-
-    return E_INVALIDARG;
-  }
+  MOZ_ASSERT(!acc->IsProxy());
 
   long relIdx = 0;
   for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
     if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
       continue;
 
     RelationType relationType = sRelationTypePairs[idx].first;
     Relation rel = acc->RelationByType(relationType);
@@ -171,43 +138,17 @@ ia2Accessible::get_relations(long aMaxRe
   if (!aRelation || !aNRelations || aMaxRelations <= 0)
     return E_INVALIDARG;
   *aNRelations = 0;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  if (acc->IsProxy()) {
-    nsTArray<RelationType> types;
-    nsTArray<nsTArray<ProxyAccessible*>> targetSets;
-    acc->Proxy()->Relations(&types, &targetSets);
-
-    size_t count = std::min(targetSets.Length(),
-                            static_cast<size_t>(aMaxRelations));
-    size_t i = 0;
-    while (i < count) {
-      uint32_t relTypeIdx = static_cast<uint32_t>(types[i]);
-      if (sRelationTypePairs[relTypeIdx].second == IA2_RELATION_NULL)
-        continue;
-
-      size_t targetCount = targetSets[i].Length();
-      nsTArray<RefPtr<Accessible>> targets(targetCount);
-      for (size_t j = 0; j < targetCount; j++)
-        targets.AppendElement(WrapperFor(targetSets[i][j]));
-
-      RefPtr<ia2AccessibleRelation> rel =
-        new ia2AccessibleRelation(types[i], Move(targets));
-      rel.forget(aRelation + i);
-      i++;
-    }
-
-    *aNRelations = i;
-    return S_OK;
-  }
+  MOZ_ASSERT(!acc->IsProxy());
 
   for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs) &&
        *aNRelations < aMaxRelations; idx++) {
     if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
       continue;
 
     RelationType relationType = sRelationTypePairs[idx].first;
     Relation rel = acc->RelationByType(relationType);
@@ -238,62 +179,52 @@ ia2Accessible::role(long* aRole)
 
 #define ROLE(_geckoRole, stringRole, atkRole, macRole, \
              msaaRole, ia2Role, nameRule) \
   case roles::_geckoRole: \
     *aRole = ia2Role; \
     break;
 
   a11y::role geckoRole;
-  if (acc->IsProxy())
-    geckoRole = acc->Proxy()->Role();
-  else
-    geckoRole = acc->Role();
+  MOZ_ASSERT(!acc->IsProxy());
+  geckoRole = acc->Role();
   switch (geckoRole) {
 #include "RoleMap.h"
     default:
       MOZ_CRASH("Unknown role.");
   }
 
 #undef ROLE
 
   // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
   // the IA2 role a ROLE_OUTLINEITEM.
-  if (acc->IsProxy()) {
-    if (geckoRole == roles::ROW && acc->Proxy()->Parent() &&
-        acc->Proxy()->Parent()->Role() == roles::TREE_TABLE)
+  MOZ_ASSERT(!acc->IsProxy());
+  if (geckoRole == roles::ROW) {
+    Accessible* xpParent = acc->Parent();
+    if (xpParent && xpParent->Role() == roles::TREE_TABLE)
       *aRole = ROLE_SYSTEM_OUTLINEITEM;
-  } else {
-    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;
 
-  if (acc->IsProxy()) {
-    acc->Proxy()->ScrollTo(aScrollType);
-  } else {
-    nsCoreUtils::ScrollTo(acc->Document()->PresShell(), acc->GetContent(),
-                          aScrollType);
-  }
+  MOZ_ASSERT(!acc->IsProxy());
+  nsCoreUtils::ScrollTo(acc->Document()->PresShell(), acc->GetContent(),
+                        aScrollType);
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::scrollToPoint(enum IA2CoordinateType aCoordType,
@@ -304,21 +235,18 @@ ia2Accessible::scrollToPoint(enum IA2Coo
   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;
 
-  if (acc->IsProxy()) {
-    acc->Proxy()->ScrollToPoint(geckoCoordType, aX, aY);
-  } else {
-    acc->ScrollToPoint(geckoCoordType, aX, aY);
-  }
+  MOZ_ASSERT(!acc->IsProxy());
+  acc->ScrollToPoint(geckoCoordType, aX, aY);
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_groupPosition(long* aGroupLevel,
@@ -368,20 +296,18 @@ ia2Accessible::get_states(AccessibleStat
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct()) {
     *aStates = IA2_STATE_DEFUNCT;
     return S_OK;
   }
 
   uint64_t state;
-  if (acc->IsProxy())
-    state = acc->Proxy()->State();
-  else
-    state = acc->State();
+  MOZ_ASSERT(!acc->IsProxy());
+  state = acc->State();
 
   if (state & states::INVALID)
     *aStates |= IA2_STATE_INVALID_ENTRY;
   if (state & states::REQUIRED)
     *aStates |= IA2_STATE_REQUIRED;
 
   // The following IA2 states are not supported by Gecko
   // IA2_STATE_ARMED
@@ -543,20 +469,18 @@ ia2Accessible::get_indexInParent(long* a
   if (!aIndexInParent)
     return E_INVALIDARG;
   *aIndexInParent = -1;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  if (acc->IsProxy())
-    *aIndexInParent = acc->Proxy()->IndexInParent();
-  else
-    *aIndexInParent = acc->IndexInParent();
+  MOZ_ASSERT(!acc->IsProxy());
+  *aIndexInParent = acc->IndexInParent();
 
   if (*aIndexInParent == -1)
     return S_FALSE;
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
@@ -627,19 +551,18 @@ ia2Accessible::get_attributes(BSTR* aAtt
 
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
   if (!acc->IsProxy()) {
     nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
     return ConvertToIA2Attributes(attributes, aAttributes);
   }
 
-  nsTArray<Attribute> attrs;
-  acc->Proxy()->Attributes(&attrs);
-  return ConvertToIA2Attributes(&attrs, aAttributes);
+  MOZ_ASSERT(!acc->IsProxy());
+  return E_UNEXPECTED;
 
   A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessible2_2
 
 STDMETHODIMP
@@ -714,31 +637,22 @@ ia2Accessible::get_relationTargetsOfType
   if (!relationType)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsTArray<Accessible*> targets;
-  if (acc->IsProxy()) {
-    nsTArray<ProxyAccessible*> targetProxies =
-      acc->Proxy()->RelationByType(*relationType);
-
-    size_t targetCount = aMaxTargets;
-    if (targetProxies.Length() < targetCount)
-      targetCount = targetProxies.Length();
-    for (size_t i = 0; i < targetCount; i++)
-      targets.AppendElement(WrapperFor(targetProxies[i]));
-  } else {
-    Relation rel = acc->RelationByType(*relationType);
-    Accessible* target = nullptr;
-    while ((target = rel.Next()) &&
-           static_cast<long>(targets.Length()) <= aMaxTargets)
-      targets.AppendElement(target);
+  MOZ_ASSERT(!acc->IsProxy());
+  Relation rel = acc->RelationByType(*relationType);
+  Accessible* target = nullptr;
+  while ((target = rel.Next()) &&
+         static_cast<long>(targets.Length()) <= aMaxTargets) {
+    targets.AppendElement(target);
   }
 
   *aNTargets = targets.Length();
   *aTargets = static_cast<IUnknown**>(
     ::CoTaskMemAlloc(sizeof(IUnknown*) * *aNTargets));
   if (!*aTargets)
     return E_OUTOFMEMORY;
 
--- a/accessible/windows/ia2/ia2AccessibleEditableText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
@@ -19,19 +19,17 @@ using namespace mozilla::a11y;
 
 // IAccessibleEditableText
 
 STDMETHODIMP
 ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    return proxy->CopyText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
-  }
+  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;
 
@@ -41,19 +39,17 @@ ia2AccessibleEditableText::copyText(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
-    if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-      return proxy->DeleteText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
-    }
+  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;
 
@@ -65,19 +61,17 @@ ia2AccessibleEditableText::deleteText(lo
 
 STDMETHODIMP
 ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
   uint32_t length = ::SysStringLen(*aText);
   nsAutoString text(*aText, length);
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    return proxy->InsertText(text, aOffset) ? S_OK : E_INVALIDARG;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidOffset(aOffset))
     return E_INVALIDARG;
 
@@ -87,19 +81,17 @@ ia2AccessibleEditableText::insertText(lo
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    return proxy->CutText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
-  }
+  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;
 
@@ -109,19 +101,17 @@ ia2AccessibleEditableText::cutText(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::pasteText(long aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    return proxy->PasteText(aOffset) ? S_OK : E_INVALIDARG;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidOffset(aOffset))
     return E_INVALIDARG;
 
--- a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -48,27 +48,17 @@ ia2AccessibleHyperlink::get_anchor(long 
   A11Y_TRYBLOCK_BEGIN
 
   if (!aAnchor)
     return E_INVALIDARG;
 
   VariantInit(aAnchor);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
-  if (thisObj->IsProxy()) {
-    ProxyAccessible* anchor = thisObj->Proxy()->AnchorAt(aIndex);
-    if (!anchor)
-      return S_FALSE;
-
-    IUnknown* tmp = static_cast<IAccessibleHyperlink*>(WrapperFor(anchor));
-    tmp->AddRef();
-    aAnchor->punkVal = tmp;
-    aAnchor->vt = VT_UNKNOWN;
-    return S_OK;
-  }
+  MOZ_ASSERT(!thisObj->IsProxy());
 
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
     return E_INVALIDARG;
 
   if (!thisObj->IsLink())
@@ -92,46 +82,45 @@ ia2AccessibleHyperlink::get_anchor(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (!aAnchorTarget)
+  if (!aAnchorTarget) {
     return E_INVALIDARG;
+  }
 
   VariantInit(aAnchorTarget);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   nsAutoCString uriStr;
-  if (thisObj->IsProxy()) {
-    bool ok;
-    thisObj->Proxy()->AnchorURIAt(aIndex, uriStr, &ok);
-    if (!ok)
-      return S_FALSE;
+  MOZ_ASSERT(!thisObj->IsProxy());
+  if (thisObj->IsDefunct()) {
+    return CO_E_OBJNOTCONNECTED;
+  }
 
-  } else {
-    if (thisObj->IsDefunct())
-      return CO_E_OBJNOTCONNECTED;
+  if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount())) {
+    return E_INVALIDARG;
+  }
 
-    if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
-      return E_INVALIDARG;
-
-    if (!thisObj->IsLink())
-      return S_FALSE;
+  if (!thisObj->IsLink()) {
+    return S_FALSE;
+  }
 
-    nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
-    if (!uri)
-      return S_FALSE;
+  nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
+  if (!uri) {
+    return S_FALSE;
+  }
 
-    nsresult rv = uri->GetSpec(uriStr);
-    if (NS_FAILED(rv))
-      return GetHRESULT(rv);
+  nsresult rv = uri->GetSpec(uriStr);
+  if (NS_FAILED(rv)) {
+    return GetHRESULT(rv);
   }
 
   nsAutoString stringURI;
   AppendUTF8toUTF16(uriStr, stringURI);
 
   aAnchorTarget->vt = VT_BSTR;
   aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
                                                stringURI.Length());
@@ -145,21 +134,17 @@ ia2AccessibleHyperlink::get_startIndex(l
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aIndex)
     return E_INVALIDARG;
 
   *aIndex = 0;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    bool valid;
-    *aIndex = proxy->StartOffset(&valid);
-    return valid ? S_OK : S_FALSE;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
@@ -174,21 +159,17 @@ ia2AccessibleHyperlink::get_endIndex(lon
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aIndex)
     return E_INVALIDARG;
 
   *aIndex = 0;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    bool valid;
-    *aIndex = proxy->EndOffset(&valid);
-    return valid ? S_OK : S_FALSE;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
@@ -203,20 +184,17 @@ ia2AccessibleHyperlink::get_valid(boolea
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aValid)
     return E_INVALIDARG;
 
   *aValid = false;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    *aValid = proxy->IsLinkValid();
-    return S_OK;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
--- a/accessible/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
@@ -21,20 +21,17 @@ ia2AccessibleHypertext::get_nHyperlinks(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlinkCount)
     return E_INVALIDARG;
 
   *aHyperlinkCount = 0;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    *aHyperlinkCount = proxy->LinkCount();
-    return S_OK;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkCount = hyperText->LinkCount();
   return S_OK;
 
@@ -48,29 +45,23 @@ ia2AccessibleHypertext::get_hyperlink(lo
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlink)
     return E_INVALIDARG;
 
   *aHyperlink = nullptr;
 
   AccessibleWrap* hyperLink;
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    ProxyAccessible* link = proxy->LinkAt(aLinkIndex);
-    if (!link)
-      return E_FAIL;
+  MOZ_ASSERT(!HyperTextProxyFor(this));
+  HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
+  if (hyperText->IsDefunct()) {
+    return CO_E_OBJNOTCONNECTED;
+  }
 
-    hyperLink = WrapperFor(link);
-  } else {
-    HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
-    if (hyperText->IsDefunct())
-      return CO_E_OBJNOTCONNECTED;
-
-    hyperLink = static_cast<AccessibleWrap*>(hyperText->LinkAt(aLinkIndex));
-  }
+  hyperLink = static_cast<AccessibleWrap*>(hyperText->LinkAt(aLinkIndex));
 
   if (!hyperLink)
     return E_FAIL;
 
   *aHyperlink =
     static_cast<IAccessibleHyperlink*>(hyperLink);
   (*aHyperlink)->AddRef();
   return S_OK;
@@ -83,20 +74,17 @@ ia2AccessibleHypertext::get_hyperlinkInd
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlinkIndex)
     return E_INVALIDARG;
 
   *aHyperlinkIndex = 0;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    *aHyperlinkIndex = proxy->LinkIndexAtOffset(aCharIndex);
-    return S_OK;
-  }
+  MOZ_ASSERT(!HyperTextProxyFor(this));
 
   HyperTextAccessibleWrap* hyperAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkIndex = hyperAcc->LinkIndexAtOffset(aCharIndex);
   return S_OK;
 
--- a/accessible/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleText.cpp
@@ -25,20 +25,17 @@ bool ia2AccessibleText::sLastTextChangeW
 
 // IAccessibleText
 
 STDMETHODIMP
 ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    return proxy->AddToSelection(aStartOffset, aEndOffset) ?
-      S_OK : E_INVALIDARG;
-  }
+  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;
 
@@ -55,31 +52,26 @@ ia2AccessibleText::get_attributes(long a
     return E_INVALIDARG;
 
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aTextAttributes = nullptr;
 
   int32_t startOffset = 0, endOffset = 0;
   HRESULT hr;
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    AutoTArray<Attribute, 10> attrs;
-    proxy->TextAttributes(true, aOffset, &attrs, &startOffset, &endOffset);
-    hr = AccessibleWrap::ConvertToIA2Attributes(&attrs, aTextAttributes);
-  } else {
-    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-    if (textAcc->IsDefunct())
-      return CO_E_OBJNOTCONNECTED;
-
-    nsCOMPtr<nsIPersistentProperties> attributes =
-      textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
-
-    hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
+  MOZ_ASSERT(!HyperTextProxyFor(this));
+  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+  if (textAcc->IsDefunct()) {
+    return CO_E_OBJNOTCONNECTED;
   }
 
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
+
+  hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
   if (FAILED(hr))
     return hr;
 
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
 
   return S_OK;
 
@@ -91,25 +83,23 @@ ia2AccessibleText::get_caretOffset(long 
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aOffset)
     return E_INVALIDARG;
 
   *aOffset = -1;
 
-  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
-    *aOffset = proxy->CaretOffset();
-  } else {
-    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-    if (textAcc->IsDefunct())
-      return CO_E_OBJNOTCONNECTED;
+  MOZ_ASSERT(!HyperTextProxyFor(this));
+  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+  if (textAcc->IsDefunct()) {
+    return CO_E_OBJNOTCONNECTED;
+  }
 
-    *aOffset = textAcc->CaretOffset();
-  }
+  *aOffset = textAcc->CaretOffset();
 
   return *aOffset != -1 ? S_OK : S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_characterExtents(long aOffset,
@@ -122,25 +112,22 @@ ia2AccessibleText::get_characterExtents(
   if (!aX || !aY || !aWidth || !aHeight)
     return E_INVALIDARG;
   *aX = *aY = *aWid