hardest merge from m-c
authorShu-yu Guo <shu@rfrn.org>
Fri, 05 Oct 2012 06:05:38 -0700
changeset 109354 632a6d9182f4869d54cc161b32b7257843a6b0ff
parent 107457 35f46b27d3126f48c9b6087a815c6ef63fcbfff9 (current diff)
parent 109353 58f3ccaa02b89bf3436a5af454cd214c1f3707ba (diff)
child 109355 41d18b2da95449b0e8ba099de6eb9246ea4727f1
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
milestone18.0a1
hardest merge from m-c
accessible/src/jsat/VirtualCursorController.jsm
browser/components/privatebrowsing/test/unit/do_test_removeDataFromDomain.js
browser/components/privatebrowsing/test/unit/do_test_removeDataFromDomain_activeDownloads.js
browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_removeDataFromDomain.js
browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_removeDataFromDomain_activeDownloads.js
browser/components/sessionstore/test/browser_586068-cascaded_restore.js
browser/components/tabview/test/browser_tabview_bug595020.js
browser/devtools/commandline/test/browser_gcli_web.js
browser/devtools/debugger/test/browser_dbg_contextactor-01.js
browser/devtools/debugger/test/browser_dbg_contextactor-02.js
browser/devtools/shared/Promise.jsm
browser/themes/pinstripe/places/starPage.png
build/valgrind/i686-redhat-linux-gnu.sup
content/base/src/nsBlobProtocolHandler.h
content/base/test/test_blobbuilder.html
content/canvas/src/CustomQS_WebGL.h
content/events/src/nsDOMMozTouchEvent.cpp
content/events/src/nsDOMMozTouchEvent.h
content/events/test/test_bug508906.html
dom/bluetooth/BluetoothUtils.h
dom/interfaces/events/nsIDOMMozTouchEvent.idl
dom/workers/FileReaderSyncPrivate.cpp
dom/workers/FileReaderSyncPrivate.h
extensions/cookie/test/test_app_uninstall.html
gfx/skia/include/core/SkAutoKern.h
gfx/skia/include/core/SkBlitter.h
gfx/skia/include/core/SkBuffer.h
gfx/skia/include/core/SkClampRange.h
gfx/skia/include/core/SkDescriptor.h
gfx/skia/include/core/SkDeviceProfile.h
gfx/skia/include/core/SkEdgeClipper.h
gfx/skia/include/core/SkFDot6.h
gfx/skia/include/core/SkGlobals.h
gfx/skia/include/core/SkOrderedReadBuffer.h
gfx/skia/include/core/SkOrderedWriteBuffer.h
gfx/skia/include/core/SkPerspIter.h
gfx/skia/include/core/SkPtrRecorder.h
gfx/skia/include/core/SkRefDict.h
gfx/skia/include/core/SkRelay.h
gfx/skia/include/core/SkScalerContext.h
gfx/skia/include/core/SkScan.h
gfx/skia/include/core/SkShape.h
gfx/skia/include/core/SkStroke.h
gfx/skia/include/effects/SkEffects.h
gfx/skia/include/effects/SkGroupShape.h
gfx/skia/include/effects/SkRectShape.h
gfx/skia/include/gpu/GrClip.h
gfx/skia/include/gpu/GrClipIterator.h
gfx/skia/include/gpu/GrGLConfig.h
gfx/skia/include/gpu/GrGLConfig_chrome.h
gfx/skia/include/gpu/GrGLDefines.h
gfx/skia/include/gpu/GrGLInterface.h
gfx/skia/include/gpu/GrPath.h
gfx/skia/include/gpu/GrTemplates.h
gfx/skia/include/gpu/SkGLContext.h
gfx/skia/include/gpu/SkMesaGLContext.h
gfx/skia/include/gpu/SkNativeGLContext.h
gfx/skia/include/gpu/SkNullGLContext.h
gfx/skia/include/pdf/SkBitSet.h
gfx/skia/include/pdf/SkPDFCatalog.h
gfx/skia/include/pdf/SkPDFFont.h
gfx/skia/include/pdf/SkPDFFormXObject.h
gfx/skia/include/pdf/SkPDFGraphicState.h
gfx/skia/include/pdf/SkPDFImage.h
gfx/skia/include/pdf/SkPDFPage.h
gfx/skia/include/pdf/SkPDFShader.h
gfx/skia/include/pdf/SkPDFStream.h
gfx/skia/include/pdf/SkPDFTypes.h
gfx/skia/include/pdf/SkPDFUtils.h
gfx/skia/include/utils/SkGLCanvas.h
gfx/skia/include/utils/SkSfntUtils.h
gfx/skia/include/utils/SkTextBox.h
gfx/skia/include/utils/android/AndroidKeyToSkKey.h
gfx/skia/include/utils/unix/XkeysToSkKeys.h
gfx/skia/include/utils/unix/keysym2ucs.h
gfx/skia/include/views/SkBorderView.h
gfx/skia/include/views/SkImageView.h
gfx/skia/include/views/SkProgressBarView.h
gfx/skia/include/views/SkScrollBarView.h
gfx/skia/include/views/SkWidgetViews.h
gfx/skia/patches/0001-Bug-687189-Implement-SkPaint-getPosTextPath.patch
gfx/skia/patches/0002-Bug-688366-Dont-invalidate-all-radial-gradients.patch
gfx/skia/patches/0003-SkUserConfig-for-Mozilla.patch
gfx/skia/patches/0004-Bug-722011-Fix-trailing-commas-in-enums.patch
gfx/skia/patches/0005-Bug-731384-Fix-clang-SK_OVERRIDE.patch
gfx/skia/patches/0006-Bug-751814-ARM-EDSP-ARMv6-Skia-fixes.patch
gfx/skia/patches/0007-Bug-719872-Old-Android-FontHost.patch
gfx/skia/patches/0008-Bug-687188-Skia-radial-gradients.patch
gfx/skia/patches/0009-Bug-755869-FreeBSD-Hurd.patch
gfx/skia/patches/0010-Bug-689069-ARM-Opts.patch
gfx/skia/patches/0011-Bug-719575-Fix-clang-build.patch
gfx/skia/patches/0012-Bug-759683-make-ssse3-conditional.patch
gfx/skia/patches/0013-Bug-761890-fonts.patch
gfx/skia/patches/0014-Bug-765038-Fix-clang-build.patch
gfx/skia/patches/0015-Bug-766017-warnings.patch
gfx/skia/patches/0016-Bug-718849-Radial-gradients.patch
gfx/skia/patches/0017-Bug-740194-SkMemory-mozalloc.patch
gfx/skia/src/animator/SkBase64.cpp
gfx/skia/src/animator/SkBase64.h
gfx/skia/src/core/SkBitmapProcState_matrix_clamp.h
gfx/skia/src/core/SkBitmapProcState_matrix_repeat.h
gfx/skia/src/core/SkClampRange.cpp
gfx/skia/src/core/SkDrawing.cpp
gfx/skia/src/core/SkGlobals.cpp
gfx/skia/src/core/SkShape.cpp
gfx/skia/src/effects/SkBitmapCache.cpp
gfx/skia/src/effects/SkBitmapCache.h
gfx/skia/src/effects/SkClampRange.cpp
gfx/skia/src/effects/SkClampRange.h
gfx/skia/src/effects/SkEffects.cpp
gfx/skia/src/effects/SkEffects_none.cpp
gfx/skia/src/effects/SkGradientShader.cpp
gfx/skia/src/effects/SkGroupShape.cpp
gfx/skia/src/effects/SkRadialGradient_Table.h
gfx/skia/src/gpu/GrAddPathRenderers_aahairline.cpp
gfx/skia/src/gpu/GrAddPathRenderers_tesselated.cpp
gfx/skia/src/gpu/GrBatchedTextContext.cpp
gfx/skia/src/gpu/GrBatchedTextContext.h
gfx/skia/src/gpu/GrClip.cpp
gfx/skia/src/gpu/GrDefaultTextContext.cpp
gfx/skia/src/gpu/GrDefaultTextContext.h
gfx/skia/src/gpu/GrGLCreateNativeInterface_none.cpp
gfx/skia/src/gpu/GrGLCreateNullInterface.cpp
gfx/skia/src/gpu/GrGLDefaultInterface_native.cpp
gfx/skia/src/gpu/GrGLDefaultInterface_none.cpp
gfx/skia/src/gpu/GrGLIRect.h
gfx/skia/src/gpu/GrGLIndexBuffer.cpp
gfx/skia/src/gpu/GrGLIndexBuffer.h
gfx/skia/src/gpu/GrGLInterface.cpp
gfx/skia/src/gpu/GrGLProgram.cpp
gfx/skia/src/gpu/GrGLProgram.h
gfx/skia/src/gpu/GrGLRenderTarget.cpp
gfx/skia/src/gpu/GrGLRenderTarget.h
gfx/skia/src/gpu/GrGLSL.cpp
gfx/skia/src/gpu/GrGLSL.h
gfx/skia/src/gpu/GrGLShaderVar.h
gfx/skia/src/gpu/GrGLStencilBuffer.cpp
gfx/skia/src/gpu/GrGLStencilBuffer.h
gfx/skia/src/gpu/GrGLTexture.cpp
gfx/skia/src/gpu/GrGLTexture.h
gfx/skia/src/gpu/GrGLUtil.cpp
gfx/skia/src/gpu/GrGLVertexBuffer.cpp
gfx/skia/src/gpu/GrGLVertexBuffer.h
gfx/skia/src/gpu/GrGpuGL.cpp
gfx/skia/src/gpu/GrGpuGL.h
gfx/skia/src/gpu/GrGpuGLFixed.cpp
gfx/skia/src/gpu/GrGpuGLFixed.h
gfx/skia/src/gpu/GrGpuGLShaders.cpp
gfx/skia/src/gpu/GrGpuGLShaders.h
gfx/skia/src/gpu/GrPrintf_printf.cpp
gfx/skia/src/gpu/GrPrintf_skia.cpp
gfx/skia/src/gpu/GrStringBuilder.h
gfx/skia/src/gpu/GrTesselatedPathRenderer.cpp
gfx/skia/src/gpu/GrTesselatedPathRenderer.h
gfx/skia/src/gpu/SkGLContext.cpp
gfx/skia/src/gpu/SkNullGLContext.cpp
gfx/skia/src/images/SkBitmap_RLEPixels.h
gfx/skia/src/images/SkCreateRLEPixelRef.cpp
gfx/skia/src/pdf/SkBitSet.cpp
gfx/skia/src/ports/SkFontHost_gamma.cpp
gfx/skia/src/ports/SkFontHost_gamma_none.cpp
gfx/skia/src/ports/SkGlobals_global.cpp
gfx/skia/src/ports/SkOSEvent_android.cpp
gfx/skia/src/ports/SkOSEvent_dummy.cpp
gfx/skia/src/ports/sk_predefined_gamma.h
gfx/skia/src/utils/SDL/SkOSWindow_SDL.cpp
gfx/skia/src/utils/SkColorMatrix.cpp
gfx/skia/src/utils/SkSfntUtils.cpp
gfx/skia/src/utils/mac/SampleApp-Info.plist
gfx/skia/src/utils/mac/SampleApp.xib
gfx/skia/src/utils/mac/SampleAppDelegate.h
gfx/skia/src/utils/mac/SampleAppDelegate.mm
gfx/skia/src/utils/mac/SkEventNotifier.h
gfx/skia/src/utils/mac/SkEventNotifier.mm
gfx/skia/src/utils/mac/SkNSView.h
gfx/skia/src/utils/mac/SkNSView.mm
gfx/skia/src/utils/mac/SkOSWindow_Mac.cpp
gfx/skia/src/utils/mac/SkOSWindow_Mac.mm
gfx/skia/src/utils/mac/SkOptionsTableView.h
gfx/skia/src/utils/mac/SkOptionsTableView.mm
gfx/skia/src/utils/mac/SkSampleNSView.h
gfx/skia/src/utils/mac/SkSampleNSView.mm
gfx/skia/src/utils/mac/SkTextFieldCell.h
gfx/skia/src/utils/mac/skia_mac.mm
gfx/skia/src/utils/unix/SkOSWindow_Unix.cpp
gfx/skia/src/utils/unix/keysym2ucs.c
gfx/skia/src/utils/win/SkOSWindow_Win.cpp
gfx/skia/src/utils/win/skia_win.cpp
gfx/skia/src/views/SkBorderView.cpp
gfx/skia/src/views/SkImageView.cpp
gfx/skia/src/views/SkListView.cpp
gfx/skia/src/views/SkListWidget.cpp
gfx/skia/src/views/SkProgressBarView.cpp
gfx/skia/src/views/SkScrollBarView.cpp
gfx/skia/src/views/SkStaticTextView.cpp
gfx/skia/src/views/SkWidgetViews.cpp
gfx/skia/third_party/glu/LICENSE.txt
gfx/skia/third_party/glu/README.skia
gfx/skia/third_party/glu/gluos.h
gfx/skia/third_party/glu/libtess/GNUmakefile
gfx/skia/third_party/glu/libtess/Imakefile
gfx/skia/third_party/glu/libtess/README
gfx/skia/third_party/glu/libtess/alg-outline
gfx/skia/third_party/glu/libtess/dict-list.h
gfx/skia/third_party/glu/libtess/dict.c
gfx/skia/third_party/glu/libtess/dict.h
gfx/skia/third_party/glu/libtess/geom.c
gfx/skia/third_party/glu/libtess/geom.h
gfx/skia/third_party/glu/libtess/memalloc.c
gfx/skia/third_party/glu/libtess/memalloc.h
gfx/skia/third_party/glu/libtess/mesh.c
gfx/skia/third_party/glu/libtess/mesh.h
gfx/skia/third_party/glu/libtess/normal.c
gfx/skia/third_party/glu/libtess/normal.h
gfx/skia/third_party/glu/libtess/priorityq-heap.c
gfx/skia/third_party/glu/libtess/priorityq-heap.h
gfx/skia/third_party/glu/libtess/priorityq-sort.h
gfx/skia/third_party/glu/libtess/priorityq.c
gfx/skia/third_party/glu/libtess/priorityq.h
gfx/skia/third_party/glu/libtess/render.c
gfx/skia/third_party/glu/libtess/render.h
gfx/skia/third_party/glu/libtess/sweep.c
gfx/skia/third_party/glu/libtess/sweep.h
gfx/skia/third_party/glu/libtess/tess.c
gfx/skia/third_party/glu/libtess/tess.h
gfx/skia/third_party/glu/libtess/tessmono.c
gfx/skia/third_party/glu/libtess/tessmono.h
gfx/skia/third_party/glu/sk_glu.h
gfx/skia/update.sh
image/test/mochitest/bug733553-iframe.html
ipc/socket/Makefile.in
ipc/socket/Socket.cpp
ipc/socket/Socket.h
js/src/Makefile.in
js/src/builtin/ParallelArray-inl.h
js/src/builtin/ParallelArray.cpp
js/src/builtin/ParallelArray.h
js/src/gc/Marking.cpp
js/src/ion/Bailouts.cpp
js/src/ion/Bailouts.h
js/src/ion/CodeGenerator.cpp
js/src/ion/CodeGenerator.h
js/src/ion/CompileInfo.h
js/src/ion/Ion.cpp
js/src/ion/Ion.h
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
js/src/ion/IonCaches.cpp
js/src/ion/IonCode.h
js/src/ion/IonFrames.cpp
js/src/ion/IonMacroAssembler.cpp
js/src/ion/LIR-Common.h
js/src/ion/LIR.h
js/src/ion/LOpcodes.h
js/src/ion/Lowering.cpp
js/src/ion/Lowering.h
js/src/ion/MIR.cpp
js/src/ion/MIR.h
js/src/ion/MOpcodes.h
js/src/ion/TypeOracle.h
js/src/ion/VMFunctions.cpp
js/src/ion/VMFunctions.h
js/src/ion/arm/Trampoline-arm.cpp
js/src/ion/shared/CodeGenerator-shared.cpp
js/src/ion/shared/CodeGenerator-shared.h
js/src/ion/x64/Trampoline-x64.cpp
js/src/ion/x86/Trampoline-x86.cpp
js/src/jit-test/tests/parallelarray/length-3.js
js/src/jit-test/tests/parallelarray/scatter-throws.js
js/src/jit-test/tests/parallelarray/shape-2.js
js/src/jit-test/tests/parallelarray/shape-4.js
js/src/jit-test/tests/parallelarray/surfaces-1.js
js/src/js.msg
js/src/jsapi.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsdbgapi.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsgcinlines.h
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsiter.cpp
js/src/jsmemorymetrics.cpp
js/src/jsobj.cpp
js/src/jsproto.tbl
js/src/jsprvtd.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsthreadpool.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
layout/svg/base/src/Makefile.in
layout/svg/base/src/SVGFEContainerFrame.cpp
layout/svg/base/src/SVGFEImageFrame.cpp
layout/svg/base/src/SVGFELeafFrame.cpp
layout/svg/base/src/SVGFEUnstyledLeafFrame.cpp
layout/svg/base/src/SVGViewFrame.cpp
layout/svg/base/src/nsISVGChildFrame.h
layout/svg/base/src/nsISVGGlyphFragmentNode.h
layout/svg/base/src/nsISVGSVGFrame.h
layout/svg/base/src/nsSVGAFrame.cpp
layout/svg/base/src/nsSVGClipPathFrame.cpp
layout/svg/base/src/nsSVGClipPathFrame.h
layout/svg/base/src/nsSVGContainerFrame.cpp
layout/svg/base/src/nsSVGContainerFrame.h
layout/svg/base/src/nsSVGEffects.cpp
layout/svg/base/src/nsSVGEffects.h
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterFrame.h
layout/svg/base/src/nsSVGFilterInstance.cpp
layout/svg/base/src/nsSVGFilterInstance.h
layout/svg/base/src/nsSVGFilterPaintCallback.h
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.h
layout/svg/base/src/nsSVGGFrame.cpp
layout/svg/base/src/nsSVGGFrame.h
layout/svg/base/src/nsSVGGenericContainerFrame.cpp
layout/svg/base/src/nsSVGGenericContainerFrame.h
layout/svg/base/src/nsSVGGeometryFrame.cpp
layout/svg/base/src/nsSVGGeometryFrame.h
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGGradientFrame.cpp
layout/svg/base/src/nsSVGGradientFrame.h
layout/svg/base/src/nsSVGImageFrame.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.h
layout/svg/base/src/nsSVGIntegrationUtils.cpp
layout/svg/base/src/nsSVGIntegrationUtils.h
layout/svg/base/src/nsSVGMarkerFrame.cpp
layout/svg/base/src/nsSVGMarkerFrame.h
layout/svg/base/src/nsSVGMaskFrame.cpp
layout/svg/base/src/nsSVGMaskFrame.h
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.h
layout/svg/base/src/nsSVGPaintServerFrame.cpp
layout/svg/base/src/nsSVGPaintServerFrame.h
layout/svg/base/src/nsSVGPathGeometryFrame.cpp
layout/svg/base/src/nsSVGPathGeometryFrame.h
layout/svg/base/src/nsSVGPatternFrame.cpp
layout/svg/base/src/nsSVGPatternFrame.h
layout/svg/base/src/nsSVGStopFrame.cpp
layout/svg/base/src/nsSVGSwitchFrame.cpp
layout/svg/base/src/nsSVGTSpanFrame.cpp
layout/svg/base/src/nsSVGTSpanFrame.h
layout/svg/base/src/nsSVGTextContainerFrame.cpp
layout/svg/base/src/nsSVGTextContainerFrame.h
layout/svg/base/src/nsSVGTextFrame.cpp
layout/svg/base/src/nsSVGTextFrame.h
layout/svg/base/src/nsSVGTextPathFrame.cpp
layout/svg/base/src/nsSVGTextPathFrame.h
layout/svg/base/src/nsSVGUseFrame.cpp
layout/svg/base/src/nsSVGUtils.cpp
layout/svg/base/src/nsSVGUtils.h
layout/svg/base/src/resources/content/svgBindings.xml
layout/svg/base/src/svg.css
media/webrtc/Android.mk
mobile/android/base/AboutHomeContent.java
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_desktop_mode.png
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable-hdpi-v11/menu_item_pressed_texture.png
mobile/android/base/resources/drawable-hdpi-v11/menu_item_texture.png
mobile/android/base/resources/drawable-hdpi/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable-hdpi/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_desktop_mode.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable-mdpi-v11/menu_item_pressed_texture.png
mobile/android/base/resources/drawable-mdpi-v11/menu_item_texture.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_desktop_mode.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable-xhdpi-v11/menu_item_pressed_texture.png
mobile/android/base/resources/drawable-xhdpi-v11/menu_item_texture.png
mobile/android/base/resources/drawable-xhdpi/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable-xhdpi/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable/ic_menu_reading_list_add.png
mobile/android/base/resources/drawable/ic_menu_reading_list_remove.png
mobile/android/base/resources/drawable/menu_item_bg.xml
mobile/android/base/resources/drawable/menu_item_default.xml
mobile/android/base/resources/drawable/menu_item_pressed.xml
mobile/android/base/resources/menu-v11/gecko_app_menu.xml.in
mobile/android/base/resources/menu-v11/titlebar_contextmenu.xml.in
mobile/android/components/SafeBrowsing.js
netwerk/base/public/nsIProxyAutoConfig.idl
netwerk/base/src/nsProxyAutoConfig.js
netwerk/base/src/nsProxyAutoConfig.manifest
netwerk/test/unit_ipc/test_cookie_wrap.js
nsprpub/configure
security/nss/lib/freebl/hasht.h
security/nss/lib/freebl/sechash.h
security/nss/lib/softoken/pk11init.h
security/nss/lib/softoken/pk11pars.h
security/nss/lib/softoken/secmodt.h
security/nss/lib/softoken/sftkmod.c
security/nss/lib/ssl/nsskea.c
testing/firebug/Makefile.in
testing/firebug/fb-test-runner.config
testing/firebug/fb_run.py
testing/firebug/installfirebug.py
testing/firebug/mozprocess/mozprocess/__init__.py
testing/firebug/mozprocess/mozprocess/killableprocess.py
testing/firebug/mozprocess/mozprocess/pid.py
testing/firebug/mozprocess/mozprocess/qijo.py
testing/firebug/mozprocess/mozprocess/winprocess.py
testing/firebug/mozprocess/mozprocess/wpk.py
testing/firebug/mozprocess/setup.py
testing/firebug/mozprofile/mozprofile/__init__.py
testing/firebug/mozprofile/mozprofile/profile.py
testing/firebug/mozprofile/setup.py
testing/firebug/mozrunner/mozrunner/__init__.py
testing/firebug/mozrunner/mozrunner/runner.py
testing/firebug/mozrunner/mozrunner/utils.py
testing/firebug/mozrunner/setup.py
testing/mochitest/MockFilePicker.jsm
testing/mochitest/specialpowers/Makefile.in
testing/mochitest/specialpowers/chrome.manifest
testing/mochitest/specialpowers/components/SpecialPowersObserver.js
testing/mochitest/specialpowers/content/specialpowers.js
testing/mochitest/specialpowers/install.rdf
testing/mochitest/specialpowers/jar.mn
testing/mochitest/tests/SimpleTest/MozillaLogger.js
testing/mochitest/tests/SimpleTest/SpecialPowersObserverAPI.js
testing/mochitest/tests/SimpleTest/specialpowersAPI.js
toolkit/components/alerts/mac/growl/CFGrowlAdditions.c
toolkit/components/alerts/mac/growl/CFGrowlAdditions.h
toolkit/components/alerts/mac/growl/CFGrowlDefines.h
toolkit/components/alerts/mac/growl/CFMutableDictionaryAdditions.c
toolkit/components/alerts/mac/growl/CFMutableDictionaryAdditions.h
toolkit/components/alerts/mac/growl/CFURLAdditions.c
toolkit/components/alerts/mac/growl/CFURLAdditions.h
toolkit/components/alerts/mac/growl/GrowlAbstractSingletonObject.h
toolkit/components/alerts/mac/growl/GrowlApplicationBridge.h
toolkit/components/alerts/mac/growl/GrowlApplicationBridge.m
toolkit/components/alerts/mac/growl/GrowlDefines.h
toolkit/components/alerts/mac/growl/GrowlDefinesInternal.h
toolkit/components/alerts/mac/growl/GrowlPathUtilities.h
toolkit/components/alerts/mac/growl/GrowlPathUtilities.m
toolkit/components/alerts/mac/growl/GrowlPathway.h
toolkit/components/alerts/mac/growl/GrowlPreferencesController.h
toolkit/components/alerts/mac/growl/GrowlTicketController.h
toolkit/components/alerts/mac/growl/Makefile.in
toolkit/components/alerts/mac/growl/license.txt
toolkit/components/alerts/mac/mozGrowlDelegate.h
toolkit/components/alerts/mac/mozGrowlDelegate.mm
toolkit/components/alerts/mac/nsAlertsImageLoadListener.h
toolkit/components/alerts/mac/nsAlertsImageLoadListener.mm
toolkit/components/alerts/mac/nsNotificationsList.h
toolkit/components/alerts/mac/nsNotificationsList.mm
toolkit/components/alerts/nsINotificationsList.idl
toolkit/crashreporter/google-breakpad/.hg_archival.txt
toolkit/crashreporter/google-breakpad/.hgsvnexternals
toolkit/crashreporter/google-breakpad/src/client/linux/android_link.h
toolkit/crashreporter/google-breakpad/src/client/linux/android_ucontext.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_extension_linux.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_exc_server.c
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_exc_server.h
toolkit/crashreporter/google-breakpad/src/client/mac/tests/auto_tempdir.h
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.sln
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.vcproj
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.cc
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.h
toolkit/crashreporter/google-breakpad/src/client/windows/unittests/gtest.gyp
toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/network_source_line_resolver.h
toolkit/crashreporter/google-breakpad/src/processor/network_interface.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_protocol.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver_server_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/source_daemon.cc
toolkit/crashreporter/google-breakpad/src/processor/udp_network.cc
toolkit/crashreporter/google-breakpad/src/processor/udp_network.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h
widget/cocoa/cursors/arrowN.tiff
widget/cocoa/cursors/arrowS.tiff
widget/cocoa/cursors/colResize.tiff
widget/cocoa/cursors/help.tiff
widget/cocoa/cursors/rowResize.tiff
widget/cocoa/cursors/sizeNE.tiff
widget/cocoa/cursors/sizeNESW.tiff
widget/cocoa/cursors/sizeNS.tiff
widget/cocoa/cursors/sizeNW.tiff
widget/cocoa/cursors/sizeNWSE.tiff
widget/cocoa/cursors/sizeSE.tiff
widget/cocoa/cursors/sizeSW.tiff
widget/cocoa/cursors/spin1.tiff
widget/cocoa/cursors/spin2.tiff
widget/cocoa/cursors/spin3.tiff
widget/cocoa/cursors/spin4.tiff
widget/cocoa/cursors/vtIBeam.tiff
widget/cocoa/cursors/zoomIn.tiff
widget/cocoa/cursors/zoomOut.tiff
widget/gtk2/gtk2compat.h
widget/tests/test_bug760802.html
xpcom/base/FunctionTimer.cpp
xpcom/base/FunctionTimer.h
--- a/.gitignore
+++ b/.gitignore
@@ -14,16 +14,17 @@ ID
 
 # User files that may appear at the root
 /.mozconfig*
 /mozconfig
 /configure
 /config.cache
 /config.log
 /.clang_complete
+/mach.ini
 
 # Empty marker file that's generated when we check out NSS
 security/manager/.nss.checkout
 
 # Build directories
 /obj*/
 
 # Build directories for js shell
@@ -40,8 +41,13 @@ js/src/tests/results-*.txt
 # Java HTML5 parser classes
 parser/html/java/htmlparser/
 parser/html/java/javaparser/
 
 # Ignore the files and directory that Eclipse IDE creates
 .project
 .cproject
 .settings/
+
+# Python virtualenv artifacts.
+python/psutil/*.so
+python/psutil/*.pyd
+python/psutil/build/
--- a/.hgignore
+++ b/.hgignore
@@ -13,16 +13,17 @@
 
 # User files that may appear at the root
 ^\.mozconfig
 ^mozconfig*
 ^configure$
 ^config\.cache$
 ^config\.log$
 ^\.clang_complete
+^mach.ini$
 
 # Empty marker file that's generated when we check out NSS
 ^security/manager/\.nss\.checkout$
 
 # Build directories
 ^obj
 
 # Build directories for js shell
@@ -40,8 +41,13 @@
 
 # SVN directories
 \.svn/
 
 # Ignore the files and directory that Eclipse IDE creates
 \.project$
 \.cproject$
 \.settings/
+
+# Python stuff installed at build time.
+^python/psutil/.*\.so
+^python/psutil/.*\.pyd
+^python/psutil/build/
rename from media/webrtc/Android.mk
rename to Android.mk
--- a/media/webrtc/Android.mk
+++ b/Android.mk
@@ -1,5 +1,5 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# empty file to block B2G/Gonk from trying to build anything inside media/webrtc
+# empty file to block B2G/Gonk from trying to build anything inside mozilla-central
--- a/accessible/src/Makefile.in
+++ b/accessible/src/Makefile.in
@@ -5,16 +5,25 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+A11Y_LOG = 0
+ifdef MOZ_DEBUG
+  A11Y_LOG = 1
+endif
+ifeq (,$(filter aurora beta release esr,$(MOZ_UPDATE_CHANNEL)))
+  A11Y_LOG = 1
+endif
+export A11Y_LOG
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 PLATFORM_DIR = atk
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 PLATFORM_DIR = \
   msaa \
   windows \
   $(null)
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -401,23 +401,19 @@ AccessibleWrap::CreateMaiInterfaces(void
     interfacesBits |= 1 << MAI_INTERFACE_IMAGE;
 
   // HyperLink interface.
   if (IsLink())
     interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
 
   if (!nsAccUtils::MustPrune(this)) {  // These interfaces require children
     // Table interface.
-    nsCOMPtr<nsIAccessibleTable> accessInterfaceTable;
-    QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                   getter_AddRefs(accessInterfaceTable));
-    if (accessInterfaceTable) {
+    if (AsTable())
       interfacesBits |= 1 << MAI_INTERFACE_TABLE;
-    }
-      
+ 
     // Selection interface.
     if (IsSelect()) {
       interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
     }
   }
 
   return interfacesBits;
 }
@@ -943,17 +939,17 @@ GetAccessibleWrap(AtkObject* aAtkObj)
   AccessibleWrap* accWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
 
   // Check if the accessible was deconstructed.
   if (!accWrap)
     return nullptr;
 
   NS_ENSURE_TRUE(accWrap->GetAtkObject() == aAtkObj, nullptr);
 
-  AccessibleWrap* appAccWrap = nsAccessNode::GetApplicationAccessible();
+  AccessibleWrap* appAccWrap = ApplicationAcc();
   if (appAccWrap != accWrap && !accWrap->IsValidObject())
     return nullptr;
 
   return accWrap;
 }
 
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
--- a/accessible/src/atk/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/ApplicationAccessibleWrap.cpp
@@ -430,26 +430,27 @@ mai_util_remove_key_event_listener (guin
     if (g_hash_table_size(sKey_listener_list) == 0) {
         gtk_key_snooper_remove(sKey_snooper_id);
     }
 }
 
 AtkObject*
 mai_util_get_root(void)
 {
-  if (nsAccessibilityService::IsShutdown()) {
-    // We've shutdown, try to use gail instead
-    // (to avoid assert in spi_atk_tidy_windows())
-    if (gail_get_root)
-      return gail_get_root();
+  ApplicationAccessible* app = ApplicationAcc();
+  if (app)
+    return app->GetAtkObject();
 
-    return nullptr;
-  }
+  // We've shutdown, try to use gail instead
+  // (to avoid assert in spi_atk_tidy_windows())
+  // XXX tbsaunde then why didn't we replace the gail atk_util impl?
+  if (gail_get_root)
+    return gail_get_root();
 
-  return nsAccessNode::GetApplicationAccessible()->GetAtkObject();
+  return nullptr;
 }
 
 G_CONST_RETURN gchar *
 mai_util_get_toolkit_name(void)
 {
     return MAI_NAME;
 }
 
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -63,8 +63,12 @@ LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
   -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(topsrcdir)/other-licenses/atk-1.0 \
   $(NULL)
+
+ifneq ($(A11Y_LOG),0)
+  DEFINES += -DA11Y_LOG
+endif
--- a/accessible/src/atk/nsAccessNodeWrap.cpp
+++ b/accessible/src/atk/nsAccessNodeWrap.cpp
@@ -33,11 +33,10 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
 }
 
 void nsAccessNodeWrap::InitAccessibility()
 {
 }
 
 void nsAccessNodeWrap::ShutdownAccessibility()
 {
-  nsAccessNode::ShutdownXPAccessibility();
 }
 
--- a/accessible/src/atk/nsMaiInterfaceEditableText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceEditableText.cpp
@@ -7,163 +7,122 @@
 #include "InterfaceInitFuncs.h"
 
 #include "HyperTextAccessible.h"
 #include "nsMai.h"
 
 #include "nsString.h"
 
 extern "C" {
-
-static gboolean
-setRunAttributesCB(AtkEditableText *aText, AtkAttributeSet *aAttribSet,
-                   gint aStartOffset, gint aEndOffset)
-{
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
-
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
-
-    nsCOMPtr<nsISupports> attrSet;
-    /* how to insert attributes into nsISupports ??? */
-
-    nsresult rv = accText->SetAttributes(aStartOffset, aEndOffset,
-                                         attrSet);
-    return NS_FAILED(rv) ? FALSE : TRUE;
-}
-
 static void
 setTextContentsCB(AtkEditableText *aText, const gchar *aString)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: setTextContentsCB, aString=%s", aString));
+  MAI_LOG_DEBUG(("EditableText: setTextContentsCB, aString=%s", aString));
 
-    NS_ConvertUTF8toUTF16 strContent(aString);
-    accText->SetTextContents(strContent);
+  NS_ConvertUTF8toUTF16 strContent(aString);
+  text->SetTextContents(strContent);
 }
 
 static void
 insertTextCB(AtkEditableText *aText,
              const gchar *aString, gint aLength, gint *aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
-
-    NS_ConvertUTF8toUTF16 strContent(aString, aLength);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    // interface changed in nsIAccessibleEditableText.idl ???
-    //
-    // int32_t pos = *aPosition;
-    // nsresult rv = accText->InsertText(strContent, aLength, &pos);
-    // *aPosition = pos;
+  NS_ConvertUTF8toUTF16 strContent(aString, aLength);
+  text->InsertText(strContent, *aPosition);
 
-    accText->InsertText(strContent, *aPosition);
-
-    MAI_LOG_DEBUG(("EditableText: insert aString=%s, aLength=%d, aPosition=%d",
-                   aString, aLength, *aPosition));
+  MAI_LOG_DEBUG(("EditableText: insert aString=%s, aLength=%d, aPosition=%d",
+                 aString, aLength, *aPosition));
 }
 
 static void
 copyTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: copyTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->CopyText(aStartPos, aEndPos);
+  MAI_LOG_DEBUG(("EditableText: copyTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->CopyText(aStartPos, aEndPos);
 }
 
 static void
 cutTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
-    MAI_LOG_DEBUG(("EditableText: cutTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->CutText(aStartPos, aEndPos);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
+
+  MAI_LOG_DEBUG(("EditableText: cutTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->CutText(aStartPos, aEndPos);
 }
 
 static void
 deleteTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: deleteTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->DeleteText(aStartPos, aEndPos);
+  MAI_LOG_DEBUG(("EditableText: deleteTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->DeleteText(aStartPos, aEndPos);
 }
 
 static void
 pasteTextCB(AtkEditableText *aText, gint aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: pasteTextCB, aPosition=%d", aPosition));
-    accText->PasteText(aPosition);
+  MAI_LOG_DEBUG(("EditableText: pasteTextCB, aPosition=%d", aPosition));
+  text->PasteText(aPosition);
 }
 }
 
 void
 editableTextInterfaceInitCB(AtkEditableTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (NS_UNLIKELY(!aIface))
     return;
 
-  aIface->set_run_attributes = setRunAttributesCB;
   aIface->set_text_contents = setTextContentsCB;
   aIface->insert_text = insertTextCB;
   aIface->copy_text = copyTextCB;
   aIface->cut_text = cutTextCB;
   aIface->delete_text = deleteTextCB;
   aIface->paste_text = pasteTextCB;
 }
--- a/accessible/src/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/src/atk/nsMaiInterfaceTable.cpp
@@ -3,443 +3,293 @@
 /* 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 "InterfaceInitFuncs.h"
 
 #include "AccessibleWrap.h"
 #include "nsAccUtils.h"
-#include "nsIAccessibleTable.h"
 #include "TableAccessible.h"
+#include "TableCellAccessible.h"
 #include "nsMai.h"
 
 #include "nsArrayUtils.h"
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkObject*
-refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
+refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nullptr);
+  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
+  if (!cell)
+    return nullptr;
 
-    nsCOMPtr<nsIAccessible> cell;
-    nsresult rv = accTable->GetCellAt(aRow, aColumn,getter_AddRefs(cell));
-    if (NS_FAILED(rv) || !cell)
-        return nullptr;
+  AtkObject* cellAtkObj = AccessibleWrap::GetAtkObject(cell);
+  if (cellAtkObj)
+    g_object_ref(cellAtkObj);
 
-    AtkObject* cellAtkObj = AccessibleWrap::GetAtkObject(cell);
-    if (cellAtkObj) {
-        g_object_ref(cellAtkObj);
-    }
-    return cellAtkObj;
+  return cellAtkObj;
 }
 
 static gint
-getIndexAtCB(AtkTable* aTable, gint aRow, gint aColumn)
+getIndexAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
     return -1;
 
-  TableAccessible* table = accWrap->AsTable();
-  NS_ENSURE_TRUE(table, -1);
-
-  return static_cast<gint>(table->CellIndexAt(aRow, aColumn));
+  return static_cast<gint>(accWrap->AsTable()->CellIndexAt(aRowIdx, aColIdx));
 }
 
 static gint
-getColumnAtIndexCB(AtkTable *aTable, gint aIndex)
+getColumnAtIndexCB(AtkTable *aTable, gint aIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (!accWrap || aIdx < 0)
     return -1;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t col;
-    nsresult rv = accTable->GetColumnIndexAt(aIndex, &col);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(col);
+    return static_cast<gint>(accWrap->AsTable()->ColIndexAt(aIdx));
 }
 
 static gint
-getRowAtIndexCB(AtkTable *aTable, gint aIndex)
+getRowAtIndexCB(AtkTable *aTable, gint aIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (!accWrap || aIdx < 0)
     return -1;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t row;
-    nsresult rv = accTable->GetRowIndexAt(aIndex, &row);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(row);
+    return static_cast<gint>(accWrap->AsTable()->RowIndexAt(aIdx));
 }
 
 static gint
 getColumnCountCB(AtkTable *aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return -1;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t count;
-    nsresult rv = accTable->GetColumnCount(&count);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(count);
+    return static_cast<gint>(accWrap->AsTable()->ColCount());
 }
 
 static gint
 getRowCountCB(AtkTable *aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return -1;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t count;
-    nsresult rv = accTable->GetRowCount(&count);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(count);
+    return static_cast<gint>(accWrap->AsTable()->RowCount());
 }
 
 static gint
-getColumnExtentAtCB(AtkTable *aTable,
-                    gint aRow, gint aColumn)
+getColumnExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
+{
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
+    return -1;
+
+    return static_cast<gint>(accWrap->AsTable()->ColExtentAt(aRowIdx, aColIdx));
+}
+
+static gint
+getRowExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return -1;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t extent;
-    nsresult rv = accTable->GetColumnExtentAt(aRow, aColumn, &extent);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(extent);
-}
-
-static gint
-getRowExtentAtCB(AtkTable *aTable,
-                 gint aRow, gint aColumn)
-{
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return -1;
-
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, -1);
-
-    int32_t extent;
-    nsresult rv = accTable->GetRowExtentAt(aRow, aColumn, &extent);
-    NS_ENSURE_SUCCESS(rv, -1);
-
-    return static_cast<gint>(extent);
+  return static_cast<gint>(accWrap->AsTable()->RowExtentAt(aRowIdx, aColIdx));
 }
 
 static AtkObject*
 getCaptionCB(AtkTable* aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return nullptr;
 
-  TableAccessible* table = accWrap->AsTable();
-  NS_ENSURE_TRUE(table, nullptr);
-
-  Accessible* caption = table->Caption();
+  Accessible* caption = accWrap->AsTable()->Caption();
   return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
 }
 
 static const gchar*
 getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nullptr);
+  nsAutoString autoStr;
+  accWrap->AsTable()->ColDescription(aColumn, autoStr);
 
-    nsAutoString autoStr;
-    nsresult rv = accTable->GetColumnDescription(aColumn, autoStr);
-    NS_ENSURE_SUCCESS(rv, nullptr);
-
-    return AccessibleWrap::ReturnString(autoStr);
+  return AccessibleWrap::ReturnString(autoStr);
 }
 
 static AtkObject*
-getColumnHeaderCB(AtkTable *aTable, gint aColumn)
+getColumnHeaderCB(AtkTable *aTable, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nullptr);
+  Accessible* cell = accWrap->AsTable()->CellAt(0, aColIdx);
+  if (!cell)
+    return nullptr;
 
-    nsCOMPtr<nsIAccessible> accCell;
-    accTable->GetCellAt(0, aColumn, getter_AddRefs(accCell));
-    if (!accCell)
-        return nullptr;
-
-    // If the cell at the first row is column header then assume it is column
-    // header for all rows,
-    if (nsAccUtils::Role(accCell) == nsIAccessibleRole::ROLE_COLUMNHEADER)
-        return AccessibleWrap::GetAtkObject(accCell);
+  // If the cell at the first row is column header then assume it is column
+  // header for all rows,
+  if (cell->Role() == roles::COLUMNHEADER)
+    return AccessibleWrap::GetAtkObject(cell);
 
-    // otherwise get column header for the data cell at the first row.
-    nsCOMPtr<nsIAccessibleTableCell> accTableCell =
-        do_QueryInterface(accCell);
+  // otherwise get column header for the data cell at the first row.
+  TableCellAccessible* tableCell = cell->AsTableCell();
+  if (!tableCell)
+    return nullptr;
 
-    if (accTableCell) {
-        nsCOMPtr<nsIArray> headerCells;
-        accTableCell->GetColumnHeaderCells(getter_AddRefs(headerCells));
-        if (headerCells) {
-            nsresult rv;
-            nsCOMPtr<nsIAccessible> accHeaderCell =
-                do_QueryElementAt(headerCells, 0, &rv);
-            NS_ENSURE_SUCCESS(rv, nullptr);
+  nsAutoTArray<Accessible*, 10> headerCells;
+  tableCell->ColHeaderCells(&headerCells);
+  if (headerCells.IsEmpty())
+    return nullptr;
 
-            return AccessibleWrap::GetAtkObject(accHeaderCell);
-        }
-    }
-
-    return nullptr;
+  return AccessibleWrap::GetAtkObject(headerCells[0]);
 }
 
 static const gchar*
 getRowDescriptionCB(AtkTable *aTable, gint aRow)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nullptr);
+  nsAutoString autoStr;
+  accWrap->AsTable()->RowDescription(aRow, autoStr);
 
-    nsAutoString autoStr;
-    nsresult rv = accTable->GetRowDescription(aRow, autoStr);
-    NS_ENSURE_SUCCESS(rv, nullptr);
-
-    return AccessibleWrap::ReturnString(autoStr);
+  return AccessibleWrap::ReturnString(autoStr);
 }
 
 static AtkObject*
-getRowHeaderCB(AtkTable *aTable, gint aRow)
+getRowHeaderCB(AtkTable *aTable, gint aRowIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nullptr);
+  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, 0);
+  if (!cell)
+    return nullptr;
 
-    nsCOMPtr<nsIAccessible> accCell;
-    accTable->GetCellAt(aRow, 0, getter_AddRefs(accCell));
-    if (!accCell)
-      return nullptr;
-
-    // If the cell at the first column is row header then assume it is row
-    // header for all columns,
-    if (nsAccUtils::Role(accCell) == nsIAccessibleRole::ROLE_ROWHEADER)
-        return AccessibleWrap::GetAtkObject(accCell);
+  // If the cell at the first column is row header then assume it is row
+  // header for all columns,
+  if (cell->Role() == roles::ROWHEADER)
+    return AccessibleWrap::GetAtkObject(cell);
 
-    // otherwise get row header for the data cell at the first column.
-    nsCOMPtr<nsIAccessibleTableCell> accTableCell =
-        do_QueryInterface(accCell);
+  // otherwise get row header for the data cell at the first column.
+  TableCellAccessible* tableCell = cell->AsTableCell();
+  if (!tableCell)
+    return nullptr;
 
-    if (accTableCell) {
-      nsCOMPtr<nsIArray> headerCells;
-      accTableCell->GetRowHeaderCells(getter_AddRefs(headerCells));
-      if (headerCells) {
-        nsresult rv;
-        nsCOMPtr<nsIAccessible> accHeaderCell =
-            do_QueryElementAt(headerCells, 0, &rv);
-        NS_ENSURE_SUCCESS(rv, nullptr);
+  nsAutoTArray<Accessible*, 10> headerCells;
+  tableCell->RowHeaderCells(&headerCells);
+  if (headerCells.IsEmpty())
+    return nullptr;
 
-        return AccessibleWrap::GetAtkObject(accHeaderCell);
-      }
-    }
-
-    return nullptr;
+  return AccessibleWrap::GetAtkObject(headerCells[0]);
 }
 
 static AtkObject*
 getSummaryCB(AtkTable *aTable)
 {
   // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
   // link an accessible object to specify a summary. There is closes method
-  // in nsIAccessibleTable::summary to get a summary as a string which is not
+  // in TableAccessible::summary to get a summary as a string which is not
   // mapped directly to ATK.
   return nullptr;
 }
 
 static gint
-getSelectedColumnsCB(AtkTable *aTable, gint **aSelected)
+getSelectedColumnsCB(AtkTable *aTable, gint** aSelected)
 {
+  *aSelected = nullptr;
+
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return 0;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, 0);
-
-    uint32_t size = 0;
-    int32_t *columns = NULL;
-    nsresult rv = accTable->GetSelectedColumnIndices(&size, &columns);
-    if (NS_FAILED(rv) || (size == 0) || !columns) {
-        *aSelected = nullptr;
-        return 0;
-    }
+  nsAutoTArray<uint32_t, 10> cols;
+  accWrap->AsTable()->SelectedColIndices(&cols);
+  if (cols.IsEmpty())
+    return 0;
 
-    gint *atkColumns = g_new(gint, size);
-    if (!atkColumns) {
-        NS_WARNING("OUT OF MEMORY");
-        return 0;
-    }
+  gint* atkColumns = g_new(gint, cols.Length());
+  if (!atkColumns) {
+    NS_WARNING("OUT OF MEMORY");
+    return 0;
+  }
 
-    //copy
-    for (uint32_t index = 0; index < size; ++index)
-        atkColumns[index] = static_cast<gint>(columns[index]);
-    nsMemory::Free(columns);
-
-    *aSelected = atkColumns;
-    return size;
+  memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t));
+  *aSelected = atkColumns;
+  return cols.Length();
 }
 
 static gint
 getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
 {
-    AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-    if (!accWrap)
-        return 0;
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (!accWrap)
+    return 0;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, 0);
+  nsAutoTArray<uint32_t, 10> rows;
+  accWrap->AsTable()->SelectedRowIndices(&rows);
 
-    uint32_t size = 0;
-    int32_t *rows = NULL;
-    nsresult rv = accTable->GetSelectedRowIndices(&size, &rows);
-    if (NS_FAILED(rv) || (size == 0) || !rows) {
-        *aSelected = nullptr;
-        return 0;
-    }
+  gint* atkRows = g_new(gint, rows.Length());
+  if (!atkRows) {
+    NS_WARNING("OUT OF MEMORY");
+    return 0;
+  }
 
-    gint *atkRows = g_new(gint, size);
-    if (!atkRows) {
-        NS_WARNING("OUT OF MEMORY");
-        return 0;
-    }
-
-    //copy
-    for (uint32_t index = 0; index < size; ++index)
-        atkRows[index] = static_cast<gint>(rows[index]);
-    nsMemory::Free(rows);
-
-    *aSelected = atkRows;
-    return size;
+  memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t));
+  *aSelected = atkRows;
+  return rows.Length();
 }
 
 static gboolean
-isColumnSelectedCB(AtkTable *aTable, gint aColumn)
-{
-    AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-    if (!accWrap)
-        return FALSE;
-
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, FALSE);
-
-    bool outValue;
-    nsresult rv = accTable->IsColumnSelected(aColumn, &outValue);
-    return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
-}
-
-static gboolean
-isRowSelectedCB(AtkTable *aTable, gint aRow)
+isColumnSelectedCB(AtkTable *aTable, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, FALSE);
-
-    bool outValue;
-    nsresult rv = accTable->IsRowSelected(aRow, &outValue);
-    return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
+  return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
 }
 
 static gboolean
-isCellSelectedCB(AtkTable *aTable, gint aRow, gint aColumn)
+isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, FALSE);
+  return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
+}
 
-    bool outValue;
-    nsresult rv = accTable->IsCellSelected(aRow, aColumn, &outValue);
-    return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
+static gboolean
+isCellSelectedCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
+{
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (!accWrap)
+    return FALSE;
+
+    return static_cast<gboolean>(accWrap->AsTable()->
+      IsCellSelected(aRowIdx, aColIdx));
 }
 }
 
 void
 tableInterfaceInitCB(AtkTableIface* aIface)
 {
   NS_ASSERTION(aIface, "no interface!");
   if (NS_UNLIKELY(!aIface))
--- a/accessible/src/atk/nsMaiInterfaceText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceText.cpp
@@ -29,23 +29,22 @@ extern "C" {
 
 static gchar*
 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
-    nsresult rv = accText->GetText(aStartOffset, aEndOffset, autoStr);
+    nsresult rv = text->GetText(aStartOffset, aEndOffset, autoStr);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
 
     //copy and return, libspi will free it.
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
@@ -54,55 +53,54 @@ static gchar*
 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
-    nsAutoString autoStr;
-    int32_t startOffset = 0, endOffset = 0;
-    nsresult rv =
-        accText->GetTextAfterOffset(aOffset, aBoundaryType,
-                                    &startOffset, &endOffset, autoStr);
-    *aStartOffset = startOffset;
-    *aEndOffset = endOffset;
+  nsAutoString autoStr;
+  int32_t startOffset = 0, endOffset = 0;
+  nsresult rv =
+    text->GetTextAfterOffset(aOffset, aBoundaryType,
+                             &startOffset, &endOffset, autoStr);
 
-    NS_ENSURE_SUCCESS(rv, nullptr);
+  *aStartOffset = startOffset;
+  *aEndOffset = endOffset;
+
+  NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gchar*
 getTextAtOffsetCB(AtkText *aText, gint aOffset,
                   AtkTextBoundary aBoundaryType,
                   gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
     int32_t startOffset = 0, endOffset = 0;
     nsresult rv =
-        accText->GetTextAtOffset(aOffset, aBoundaryType,
-                                 &startOffset, &endOffset, autoStr);
+        text->GetTextAtOffset(aOffset, aBoundaryType,
+                              &startOffset, &endOffset, autoStr);
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
@@ -110,25 +108,24 @@ getTextAtOffsetCB(AtkText *aText, gint a
 
 static gunichar
 getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-  nsCOMPtr<nsIAccessibleText> accText;
-  accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                          getter_AddRefs(accText));
-  NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
   // PRUnichar is unsigned short in Mozilla
   // gnuichar is guint32 in glib
   PRUnichar uniChar = 0;
-  nsresult rv = accText->GetCharacterAtOffset(aOffset, &uniChar);
+  nsresult rv = text->GetCharacterAtOffset(aOffset, &uniChar);
   if (NS_FAILED(rv))
     return 0;
 
   // Convert char to "*" when it's "password text".
   if (accWrap->NativeRole() == roles::PASSWORD_TEXT)
     uniChar = '*';
 
   return static_cast<gunichar>(uniChar);
@@ -138,26 +135,25 @@ static gchar*
 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                       AtkTextBoundary aBoundaryType,
                       gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
     int32_t startOffset = 0, endOffset = 0;
     nsresult rv =
-        accText->GetTextBeforeOffset(aOffset, aBoundaryType,
-                                     &startOffset, &endOffset, autoStr);
+        text->GetTextBeforeOffset(aOffset, aBoundaryType,
+                                  &startOffset, &endOffset, autoStr);
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
@@ -165,145 +161,138 @@ getTextBeforeOffsetCB(AtkText *aText, gi
 
 static gint
 getCaretOffsetCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
     int32_t offset;
-    nsresult rv = accText->GetCaretOffset(&offset);
+    nsresult rv = text->GetCaretOffset(&offset);
     return (NS_FAILED(rv)) ? 0 : static_cast<gint>(offset);
 }
 
 static AtkAttributeSet*
 getRunAttributesCB(AtkText *aText, gint aOffset,
                    gint *aStartOffset,
                    gint *aEndOffset)
 {
   *aStartOffset = -1;
   *aEndOffset = -1;
 
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsCOMPtr<nsIPersistentProperties> attributes;
     int32_t startOffset = 0, endOffset = 0;
-    nsresult rv = accText->GetTextAttributes(false, aOffset,
-                                             &startOffset, &endOffset,
-                                             getter_AddRefs(attributes));
+    nsresult rv = text->GetTextAttributes(false, aOffset,
+                                          &startOffset, &endOffset,
+                                          getter_AddRefs(attributes));
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     return ConvertToAtkAttributeSet(attributes);
 }
 
 static AtkAttributeSet*
 getDefaultAttributesCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsCOMPtr<nsIPersistentProperties> attributes;
-    nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
+    nsresult rv = text->GetDefaultTextAttributes(getter_AddRefs(attributes));
     if (NS_FAILED(rv))
         return nullptr;
 
     return ConvertToAtkAttributeSet(attributes);
 }
 
 static void
 getCharacterExtentsCB(AtkText *aText, gint aOffset,
                       gint *aX, gint *aY,
                       gint *aWidth, gint *aHeight,
                       AtkCoordType aCoords)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if(!accWrap || !aX || !aY || !aWidth || !aHeight)
     return;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
     int32_t extY = 0, extX = 0;
     int32_t extWidth = 0, extHeight = 0;
 
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
 #ifdef DEBUG
     nsresult rv =
 #endif
-    accText->GetCharacterExtents(aOffset, &extX, &extY,
-                                 &extWidth, &extHeight,
-                                 geckoCoordType);
+    text->GetCharacterExtents(aOffset, &extX, &extY,
+                              &extWidth, &extHeight,
+                              geckoCoordType);
     *aX = extX;
     *aY = extY;
     *aWidth = extWidth;
     *aHeight = extHeight;
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "MaiInterfaceText::GetCharacterExtents, failed\n");
 }
 
 static void
 getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
                   AtkCoordType aCoords, AtkTextRectangle *aRect)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if(!accWrap || !aRect)
     return;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
     int32_t extY = 0, extX = 0;
     int32_t extWidth = 0, extHeight = 0;
 
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
 #ifdef DEBUG
     nsresult rv =
 #endif
-    accText->GetRangeExtents(aStartOffset, aEndOffset,
-                             &extX, &extY,
-                             &extWidth, &extHeight,
-                             geckoCoordType);
+    text->GetRangeExtents(aStartOffset, aEndOffset,
+                          &extX, &extY,
+                          &extWidth, &extHeight,
+                          geckoCoordType);
     aRect->x = extX;
     aRect->y = extY;
     aRect->width = extWidth;
     aRect->height = extHeight;
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "MaiInterfaceText::GetRangeExtents, failed\n");
 }
 
@@ -323,66 +312,63 @@ static gint
 getOffsetAtPointCB(AtkText *aText,
                    gint aX, gint aY,
                    AtkCoordType aCoords)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return -1;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, -1);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return -1;
 
     int32_t offset = 0;
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
-    accText->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
+    text->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
     return static_cast<gint>(offset);
 }
 
 static gint
 getTextSelectionCountCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
     int32_t selectionCount;
-    nsresult rv = accText->GetSelectionCount(&selectionCount);
+    nsresult rv = text->GetSelectionCount(&selectionCount);
  
     return NS_FAILED(rv) ? 0 : selectionCount;
 }
 
 static gchar*
 getTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     int32_t startOffset = 0, endOffset = 0;
-    nsresult rv = accText->GetSelectionBounds(aSelectionNum,
-                                              &startOffset, &endOffset);
+    nsresult rv = text->GetSelectionBounds(aSelectionNum,
+                                           &startOffset, &endOffset);
 
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return getTextCB(aText, *aStartOffset, *aEndOffset);
 }
@@ -392,75 +378,71 @@ static gboolean
 addTextSelectionCB(AtkText *aText,
                    gint aStartOffset,
                    gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->AddSelection(aStartOffset, aEndOffset);
+    nsresult rv = text->AddSelection(aStartOffset, aEndOffset);
 
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 removeTextSelectionCB(AtkText *aText,
                       gint aSelectionNum)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->RemoveSelection(aSelectionNum);
+    nsresult rv = text->RemoveSelection(aSelectionNum);
 
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 setTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->SetSelectionBounds(aSelectionNum,
-                                              aStartOffset, aEndOffset);
+    nsresult rv = text->SetSelectionBounds(aSelectionNum,
+                                           aStartOffset, aEndOffset);
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 setCaretOffsetCB(AtkText *aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->SetCaretOffset(aOffset);
+    nsresult rv = text->SetCaretOffset(aOffset);
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 }
 
 void
 textInterfaceInitCB(AtkTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -122,20 +122,18 @@ AccEvent::CaptureIsFromUserInput(EIsFrom
 {
   nsINode *targetNode = GetNode();
 
 #ifdef DEBUG
   if (!targetNode) {
     // XXX: remove this hack during reorganization of 506907. Meanwhile we
     // want to get rid an assertion for application accessible events which
     // don't have DOM node (see bug 506206).
-    ApplicationAccessible* applicationAcc =
-      nsAccessNode::GetApplicationAccessible();
 
-    if (mAccessible != static_cast<nsIAccessible*>(applicationAcc))
+    if (mAccessible != static_cast<nsIAccessible*>(ApplicationAcc()))
       NS_ASSERTION(targetNode, "There should always be a DOM node for an event");
   }
 #endif
 
   if (aIsFromUserInput != eAutoDetect) {
     mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
     return;
   }
--- a/accessible/src/base/FocusManager.cpp
+++ b/accessible/src/base/FocusManager.cpp
@@ -109,18 +109,20 @@ FocusManager::IsInOrContainsFocus(const 
   }
 
   return eNone;
 }
 
 void
 FocusManager::NotifyOfDOMFocus(nsISupports* aTarget)
 {
-  A11YDEBUG_FOCUS_NOTIFICATION_SUPPORTSTARGET("DOM focus", "DOM focus target",
-                                              aTarget)
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eFocus))
+    logging::FocusNotificationTarget("DOM focus", "Target", aTarget);
+#endif
 
   mActiveItem = nullptr;
 
   nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTarget));
   if (targetNode) {
     DocAccessible* document =
       GetAccService()->GetDocAccessible(targetNode->OwnerDoc());
     if (document) {
@@ -135,18 +137,20 @@ FocusManager::NotifyOfDOMFocus(nsISuppor
         (this, &FocusManager::ProcessDOMFocus, targetNode);
     }
   }
 }
 
 void
 FocusManager::NotifyOfDOMBlur(nsISupports* aTarget)
 {
-  A11YDEBUG_FOCUS_NOTIFICATION_SUPPORTSTARGET("DOM blur", "DOM blur target",
-                                              aTarget)
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eFocus))
+    logging::FocusNotificationTarget("DOM blur", "Target", aTarget);
+#endif
 
   mActiveItem = nullptr;
 
   // If DOM document stays focused then fire accessible focus event to process
   // the case when no element within this DOM document will be focused.
   nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTarget));
   if (targetNode && targetNode->OwnerDoc() == FocusedDOMDocument()) {
     nsIDocument* DOMDoc = targetNode->OwnerDoc();
@@ -157,28 +161,33 @@ FocusManager::NotifyOfDOMBlur(nsISupport
         (this, &FocusManager::ProcessDOMFocus, DOMDoc);
     }
   }
 }
 
 void
 FocusManager::ActiveItemChanged(Accessible* aItem, bool aCheckIfActive)
 {
-  A11YDEBUG_FOCUS_NOTIFICATION_ACCTARGET("active item changed",
-                                         "Active item", aItem)
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eFocus))
+    logging::FocusNotificationTarget("active item changed", "Item", aItem);
+#endif
 
   // Nothing changed, happens for XUL trees and HTML selects.
   if (aItem && aItem == mActiveItem)
     return;
 
   mActiveItem = nullptr;
 
   if (aItem && aCheckIfActive) {
     Accessible* widget = aItem->ContainerWidget();
-    A11YDEBUG_FOCUS_LOG_WIDGET("Active item widget", widget)
+#ifdef A11Y_LOG
+    if (logging::IsEnabled(logging::eFocus))
+      logging::ActiveWidget(widget);
+#endif
     if (!widget || !widget->IsActiveWidget() || !widget->AreItemsOperable())
       return;
   }
   mActiveItem = aItem;
 
   // If active item is changed then fire accessible focus event on it, otherwise
   // if there's no an active item then fire focus event to accessible having
   // DOM focus.
@@ -207,25 +216,30 @@ FocusManager::DispatchFocusEvent(DocAcce
 {
   NS_PRECONDITION(aDocument, "No document for focused accessible!");
   if (aDocument) {
     nsRefPtr<AccEvent> event =
       new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, aTarget,
                    eAutoDetect, AccEvent::eCoalesceOfSameType);
     aDocument->FireDelayedAccessibleEvent(event);
 
-    A11YDEBUG_FOCUS_LOG_ACCTARGET("Focus notification", aTarget)
+#ifdef A11Y_LOG
+    if (logging::IsEnabled(logging::eFocus))
+      logging::FocusDispatched(aTarget);
+#endif
   }
 }
 
 void
 FocusManager::ProcessDOMFocus(nsINode* aTarget)
 {
-  A11YDEBUG_FOCUS_NOTIFICATION_DOMTARGET("Process DOM focus",
-                                         "Notification target", aTarget)
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eFocus))
+    logging::FocusNotificationTarget("process DOM focus", "Target", aTarget);
+#endif
 
   DocAccessible* document =
     GetAccService()->GetDocAccessible(aTarget->OwnerDoc());
 
   Accessible* target = document->GetAccessibleOrContainer(aTarget);
   if (target && document) {
     // Check if still focused. Otherwise we can end up with storing the active
     // item for control that isn't focused anymore.
@@ -303,18 +317,20 @@ FocusManager::ProcessFocusEvent(AccEvent
     nsRefPtr<AccEvent> menuEndEvent =
       new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mActiveARIAMenubar,
                    fromUserInputFlag);
     nsEventShell::FireEvent(menuEndEvent);
 
     mActiveARIAMenubar = nullptr;
   }
 
-  A11YDEBUG_FOCUS_NOTIFICATION_ACCTARGET("FIRE FOCUS EVENT", "Focus target",
-                                         target)
+#ifdef A11Y_LOG
+  if (logging::IsEnabled(logging::eFocus))
+    logging::FocusNotificationTarget("fire focus event", "Target", target);
+#endif
 
   nsRefPtr<AccEvent> focusEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, target, fromUserInputFlag);
   nsEventShell::FireEvent(focusEvent);
 
   // Fire scrolling_start event when the document receives the focus if it has
   // an anchor jump. If an accessible within the document receive the focus
   // then null out the anchor jump because it no longer applies.
--- a/accessible/src/base/FocusManager.h
+++ b/accessible/src/base/FocusManager.h
@@ -123,131 +123,9 @@ private:
 private:
   nsRefPtr<Accessible> mActiveItem;
   nsRefPtr<Accessible> mActiveARIAMenubar;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
-
-//#define A11YDEBUG_FOCUS
-
-#ifdef A11YDEBUG_FOCUS
-
-// Util macros (don't use them directly)
-#define A11YDEBUG_FOCUS_STARTBLOCK                                             \
-  printf("  {\n    ");
-
-#define A11YDEBUG_FOCUS_ENDBLOCK                                               \
-  printf("\n  }\n");
-
-#define A11YDEBUG_FOCUS_BLOCKOFFSET                                            \
-  printf("    ");
-
-#define A11YDEBUG_FOCUS_LOG_TIME                                               \
-  {                                                                            \
-    PRIntervalTime time = PR_IntervalNow();                                    \
-    uint32_t mins = (PR_IntervalToSeconds(time) / 60) % 60;                    \
-    uint32_t secs = PR_IntervalToSeconds(time) % 60;                           \
-    uint32_t msecs = PR_IntervalToMilliseconds(time) % 1000;                   \
-    printf("Time: %2d:%2d.%3d\n", mins, secs, msecs);                          \
-  }
-
-#define A11YDEBUG_FOCUS_LOG_DOMNODE(aNode)                                     \
-  if (aNode) {                                                                 \
-    if (aNode->IsElement()) {                                                  \
-      dom::Element* targetElm = aNode->AsElement();                            \
-      nsAutoCString tag;                                                       \
-      targetElm->Tag()->ToUTF8String(tag);                                     \
-      nsAutoCString id;                                                        \
-      nsIAtom* atomid = targetElm->GetID();                                    \
-      if (atomid)                                                              \
-        atomid->ToUTF8String(id);                                              \
-      printf("element %s@id='%s': %p", tag.get(), id.get(), (void*)aNode);     \
-    } else if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {                      \
-      nsCOMPtr<nsIDocument> document = do_QueryInterface(aNode);               \
-      nsIURI* uri = document->GetDocumentURI();                                \
-      nsAutoCString spec;                                                      \
-      uri->GetSpec(spec);                                                      \
-      printf("document: %p; uri: %s", (void*)aNode, spec.get());               \
-    }                                                                          \
-  }
-
-#define A11YDEBUG_FOCUS_LOG_ACCESSIBLE(aAccessible)                            \
-  printf("accessible: %p; ", (void*)aAccessible);                              \
-  if (aAccessible) {                                                           \
-    nsAutoString role;                                                         \
-    GetAccService()->GetStringRole(aAccessible->Role(), role);                 \
-    nsAutoString name;                                                         \
-    aAccessible->Name(name);                                                   \
-    printf(" role: %s, name: %s; ", NS_ConvertUTF16toUTF8(role).get(),         \
-           NS_ConvertUTF16toUTF8(name).get());                                 \
-    A11YDEBUG_FOCUS_LOG_DOMNODE(aAccessible->GetNode())                        \
-  }
-
-// Public macros
-#define A11YDEBUG_FOCUS_LOG_DOMTARGET(aMsg, aTarget)                           \
-  A11YDEBUG_FOCUS_STARTBLOCK                                                   \
-  printf(aMsg "\n");                                                           \
-  if (aTarget) {                                                               \
-    A11YDEBUG_FOCUS_BLOCKOFFSET                                                \
-    A11YDEBUG_FOCUS_LOG_DOMNODE(aTarget)                                       \
-  }                                                                            \
-  A11YDEBUG_FOCUS_ENDBLOCK
-
-#define A11YDEBUG_FOCUS_LOG_ACCTARGET(aMsg, aTarget)                           \
-  A11YDEBUG_FOCUS_STARTBLOCK                                                   \
-  printf(aMsg "\n");                                                           \
-  A11YDEBUG_FOCUS_BLOCKOFFSET                                                  \
-  A11YDEBUG_FOCUS_LOG_ACCESSIBLE(aTarget)                                      \
-  A11YDEBUG_FOCUS_ENDBLOCK
-
-#define A11YDEBUG_FOCUS_LOG_WIDGET(aMsg, aWidget)                              \
-  A11YDEBUG_FOCUS_STARTBLOCK                                                   \
-  printf(aMsg "\n");                                                           \
-  A11YDEBUG_FOCUS_BLOCKOFFSET                                                  \
-  A11YDEBUG_FOCUS_LOG_ACCESSIBLE(aWidget)                                      \
-  printf("; widget is active: %s, has operable items: %s",                     \
-         (aWidget && aWidget->IsActiveWidget() ? "true" : "false"),            \
-         (aWidget && aWidget->AreItemsOperable() ? "true" : "false"));         \
-  A11YDEBUG_FOCUS_ENDBLOCK
-
-#define A11YDEBUG_FOCUS_NOTIFICATION_SUPPORTSTARGET(aMsg, aTargetMsg, aTarget) \
-  printf("\nA11Y FOCUS: " aMsg ". ");                                          \
-  A11YDEBUG_FOCUS_LOG_TIME                                                     \
-  if (aTarget) {                                                               \
-    A11YDEBUG_FOCUS_STARTBLOCK                                                 \
-    printf(aTargetMsg "\n");                                                   \
-    A11YDEBUG_FOCUS_BLOCKOFFSET                                                \
-    nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTarget));                  \
-    if (targetNode) {                                                          \
-      A11YDEBUG_FOCUS_LOG_DOMNODE(targetNode)                                  \
-    } else {                                                                   \
-      printf("window: %p", (void*)aTarget);                                    \
-    }                                                                          \
-    A11YDEBUG_FOCUS_ENDBLOCK                                                   \
-  }
-
-#define A11YDEBUG_FOCUS_NOTIFICATION_DOMTARGET(aMsg, aTargetMsg, aTarget)      \
-  printf("\nA11Y FOCUS: " aMsg ". ");                                          \
-  A11YDEBUG_FOCUS_LOG_TIME                                                     \
-  A11YDEBUG_FOCUS_LOG_DOMTARGET(aTargetMsg, aTarget)
-
-#define A11YDEBUG_FOCUS_NOTIFICATION_ACCTARGET(aMsg, aTargetMsg, aTarget)      \
-  printf("\nA11Y FOCUS: " aMsg ". ");                                          \
-  A11YDEBUG_FOCUS_LOG_TIME                                                     \
-  A11YDEBUG_FOCUS_LOG_ACCTARGET(aTargetMsg, aTarget)
-
-#define A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE(aMsg, aTarget)                  \
-  A11YDEBUG_FOCUS_LOG_ACCTARGET("Caused by: " aMsg, aTarget)
-
-#else
-#define A11YDEBUG_FOCUS_LOG_DOMTARGET(aMsg, aTarget)
-#define A11YDEBUG_FOCUS_LOG_ACCTARGET(aMsg, aTarget)
-#define A11YDEBUG_FOCUS_LOG_WIDGET(aMsg, aWidget)
-#define A11YDEBUG_FOCUS_NOTIFICATION_SUPPORTSTARGET(aMsg, aTargetMsg, aTarget)
-#define A11YDEBUG_FOCUS_NOTIFICATION_DOMTARGET(aMsg, aTargetMsg, aTarget)
-#define A11YDEBUG_FOCUS_NOTIFICATION_ACCTARGET(aMsg, aTargetMsg, aTarget)
-#define A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE(aMsg, aTarget)
 #endif
-
-#endif
--- a/accessible/src/base/Logging.cpp
+++ b/accessible/src/base/Logging.cpp
@@ -1,16 +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/. */
 
 #include "Logging.h"
 
+#include "Accessible-inl.h"
 #include "AccEvent.h"
 #include "DocAccessible.h"
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 #include "OuterDocAccessible.h"
 
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
@@ -345,16 +346,17 @@ GetDocLoadEventType(AccEvent* aEvent, ns
 
 ////////////////////////////////////////////////////////////////////////////////
 // namespace logging:: document life cycle logging methods
 
 static const char* sDocLoadTitle = "DOCLOAD";
 static const char* sDocCreateTitle = "DOCCREATE";
 static const char* sDocDestroyTitle = "DOCDESTROY";
 static const char* sDocEventTitle = "DOCEVENT";
+static const char* sFocusTitle = "FOCUS";
 
 void
 logging::DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
                  nsIRequest* aRequest, uint32_t aStateFlags)
 {
   MsgBegin(sDocLoadTitle, aMsg);
 
   nsCOMPtr<nsIDOMWindow> DOMWindow;
@@ -461,16 +463,82 @@ void
 logging::OuterDocDestroy(OuterDocAccessible* aOuterDoc)
 {
   MsgBegin(sDocDestroyTitle, "outerdoc shutdown");
   logging::Address("outerdoc", aOuterDoc);
   MsgEnd();
 }
 
 void
+logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                                 Accessible* aTarget)
+{
+  MsgBegin(sFocusTitle, aMsg);
+  AccessibleNNode(aTargetDescr, aTarget);
+  MsgEnd();
+}
+
+void
+logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                                 nsINode* aTargetNode)
+{
+  MsgBegin(sFocusTitle, aMsg);
+  Node(aTargetDescr, aTargetNode);
+  MsgEnd();
+}
+
+void
+logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                                 nsISupports* aTargetThing)
+{
+  MsgBegin(sFocusTitle, aMsg);
+
+  if (aTargetThing) {
+    nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTargetThing));
+    if (targetNode)
+      Node(aTargetDescr, targetNode);
+    else
+      printf("    %s: %p, window\n", aTargetDescr,
+             static_cast<void*>(aTargetThing));
+  }
+
+  MsgEnd();
+}
+
+void
+logging::ActiveItemChangeCausedBy(const char* aCause, Accessible* aTarget)
+{
+  SubMsgBegin();
+  printf("    Caused by: %s\n", aCause);
+  AccessibleNNode("Item", aTarget);
+  SubMsgEnd();
+}
+
+void
+logging::ActiveWidget(Accessible* aWidget)
+{
+  SubMsgBegin();
+
+  AccessibleNNode("Widget", aWidget);
+  printf("    Widget is active: %s, has operable items: %s\n",
+         (aWidget && aWidget->IsActiveWidget() ? "true" : "false"),
+         (aWidget && aWidget->AreItemsOperable() ? "true" : "false"));
+
+  SubMsgEnd();
+}
+
+void
+logging::FocusDispatched(Accessible* aTarget)
+{
+  SubMsgBegin();
+  AccessibleNNode("A11y target", aTarget);
+  SubMsgEnd();
+}
+
+void
 logging::SelChange(nsISelection* aSelection, DocAccessible* aDocument)
 {
   nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
 
   int16_t type = 0;
   privSel->GetType(&type);
 
   const char* strType = 0;
@@ -491,26 +559,44 @@ logging::MsgBegin(const char* aTitle, co
 {
   printf("\nA11Y %s: ", aTitle);
 
   va_list argptr;
   va_start(argptr, aMsgText);
   vprintf(aMsgText, argptr);
   va_end(argptr);
 
+  PRIntervalTime time = PR_IntervalNow();
+  uint32_t mins = (PR_IntervalToSeconds(time) / 60) % 60;
+  uint32_t secs = PR_IntervalToSeconds(time) % 60;
+  uint32_t msecs = PR_IntervalToMilliseconds(time) % 1000;
+  printf("; %02d:%02d.%03d", mins, secs, msecs);
+
   printf("\n  {\n");
 }
 
 void
 logging::MsgEnd()
 {
   printf("  }\n");
 }
 
 void
+logging::SubMsgBegin()
+{
+  printf("  {\n");
+}
+
+void
+logging::SubMsgEnd()
+{
+  printf("  }\n");
+}
+
+void
 logging::MsgEntry(const char* aEntryText, ...)
 {
   printf("    ");
 
   va_list argptr;
   va_start(argptr, aEntryText);
   vprintf(aEntryText, argptr);
   va_end(argptr);
@@ -582,16 +668,44 @@ logging::Node(const char* aDescr, nsINod
   if (idAtom)
     idAtom->ToUTF8String(id);
 
   printf("%s: %p, %s@id='%s', idx in parent: %d\n",
          aDescr, static_cast<void*>(elm), tag.get(), id.get(), idxInParent);
 }
 
 void
+logging::AccessibleNNode(const char* aDescr, Accessible* aAccessible)
+{
+  printf("    %s: %p; ", aDescr, static_cast<void*>(aAccessible));
+  if (!aAccessible)
+    return;
+
+  nsAutoString role;
+  GetAccService()->GetStringRole(aAccessible->Role(), role);
+  nsAutoString name;
+  aAccessible->Name(name);
+
+  printf("role: %s, name: '%s';\n", NS_ConvertUTF16toUTF8(role).get(),
+         NS_ConvertUTF16toUTF8(name).get());
+
+  nsAutoCString nodeDescr(aDescr);
+  nodeDescr.AppendLiteral(" node");
+  Node(nodeDescr.get(), aAccessible->GetNode());
+
+  printf("    Document: %p, document node: %p\n",
+         static_cast<void*>(aAccessible->Document()),
+         static_cast<void*>(aAccessible->GetDocumentNode()));
+
+  printf("    Document");
+  LogDocURI(static_cast<nsIDocument*>(aAccessible->GetDocumentNode()));
+  printf("\n");
+}
+
+void
 logging::Stack()
 {
   if (IsEnabled(eStack)) {
     printf("  stack: \n");
     nsTraceRefcntImpl::WalkTheStack(stdout);
   }
 }
 
--- a/accessible/src/base/Logging.h
+++ b/accessible/src/base/Logging.h
@@ -80,29 +80,61 @@ void DocDestroy(const char* aMsg, nsIDoc
                 DocAccessible* aDocument = nullptr);
 
 /**
  * Log the outer document was destroyed.
  */
 void OuterDocDestroy(OuterDocAccessible* OuterDoc);
 
 /**
+ * Log the focus notification target.
+ */
+void FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                             Accessible* aTarget);
+void FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                             nsINode* aTargetNode);
+void FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
+                             nsISupports* aTargetThing);
+
+/**
+ * Log a cause of active item descendant change (submessage).
+ */
+void ActiveItemChangeCausedBy(const char* aMsg, Accessible* aTarget);
+
+/**
+ * Log the active widget (submessage).
+ */
+void ActiveWidget(Accessible* aWidget);
+
+/**
+ * Log the focus event was dispatched (submessage).
+ */
+void FocusDispatched(Accessible* aTarget);
+
+/**
  * Log the selection change.
  */
 void SelChange(nsISelection* aSelection, DocAccessible* aDocument);
 
 /**
  * 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).
  */
 void MsgBegin(const char* aTitle, const char* aMsgText, ...);
 void MsgEnd();
 
 /**
+ * Print start and end boundaries of the message body designated by '{' and '}'
+ * (2 spaces indent for body).
+ */
+void SubMsgBegin();
+void SubMsgEnd();
+
+/**
  * Log the entry into message body (4 spaces indent).
  */
 void MsgEntry(const char* aEntryText, ...);
 
 /**
  * Log the text, two spaces offset is used.
  */
 void Text(const char* aText);
@@ -113,16 +145,21 @@ void Text(const char* aText);
 void Address(const char* aDescr, Accessible* aAcc);
 
 /**
  * Log the DOM node info as message entry.
  */
 void Node(const char* aDescr, nsINode* aNode);
 
 /**
+ * Log the accessible and its DOM node as a message entry.
+ */
+void AccessibleNNode(const char* aDescr, Accessible* aAccessible);
+
+/**
  * Log the call stack, two spaces offset is used.
  */
 void Stack();
 
 /**
  * Enable logging of the specified modules, all other modules aren't logged.
  */
 void Enable(const nsAFlatCString& aModules);
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -35,17 +35,17 @@ CPPSRCS = \
   nsCaretAccessible.cpp \
   nsTextEquivUtils.cpp \
   RoleAsserts.cpp \
   StyleInfo.cpp \
   TextAttrs.cpp \
   TextUpdater.cpp \
   $(NULL)
 
-ifdef MOZ_DEBUG
+ifneq ($(A11Y_LOG),0)
 CPPSRCS += \
   Logging.cpp \
   $(NULL)
 endif
 
 EXPORTS = \
   a11yGeneric.h \
   AccEvent.h \
@@ -101,8 +101,12 @@ LOCAL_INCLUDES += \
   $(NULL)
 else
 LOCAL_INCLUDES += \
   -I$(srcdir)/../other \
   $(NULL)
 endif
 endif
 endif
+
+ifneq ($(A11Y_LOG),0)
+  DEFINES += -DA11Y_LOG
+endif
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -11,17 +11,17 @@
 #include "nsCoreUtils.h"
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "FocusManager.h"
 #include "Role.h"
 #include "TextLeafAccessible.h"
 #include "TextUpdater.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -193,17 +193,17 @@ NotificationController::WillRefresh(mozi
   if (!mDocument->HasLoadState(DocAccessible::eTreeConstructed)) {
     // If document is not bound to parent at this point then the document is not
     // ready yet (process notifications later).
     if (!mDocument->IsBoundToParent()) {
       mObservingState = eRefreshObserving;
       return;
     }
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eTree)) {
       logging::MsgBegin("TREE", "initial tree created");
       logging::Address("document", mDocument);
       logging::MsgEnd();
     }
 #endif
 
     mDocument->DoInitialUpdate();
@@ -298,17 +298,17 @@ NotificationController::WillRefresh(mozi
   // process it synchronously.
   mObservingState = eRefreshObserving;
 
   // Process only currently queued events.
   nsTArray<nsRefPtr<AccEvent> > events;
   events.SwapElements(mEvents);
 
   uint32_t eventCount = events.Length();
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (eventCount > 0 && logging::IsEnabled(logging::eEvents)) {
     logging::MsgBegin("EVENTS", "events processing");
     logging::Address("document", mDocument);
     logging::MsgEnd();
   }
 #endif
 
   for (uint32_t idx = 0; idx < eventCount; idx++) {
@@ -723,31 +723,31 @@ NotificationController::TextEnumerator(n
     containerNode->AsElement() : nullptr;
 
   nsAutoString text;
   textFrame->GetRenderedText(&text);
 
   // Remove text accessible if rendered text is empty.
   if (textAcc) {
     if (text.IsEmpty()) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
       if (logging::IsEnabled(logging::eTree | logging::eText)) {
         logging::MsgBegin("TREE", "text node lost its content");
         logging::Node("container", containerElm);
         logging::Node("content", textNode);
         logging::MsgEnd();
       }
 #endif
 
       document->ContentRemoved(containerElm, textNode);
       return PL_DHASH_NEXT;
     }
 
     // Update text of the accessible and fire text change events.
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eText)) {
       logging::MsgBegin("TEXT", "text may be changed");
       logging::Node("container", containerElm);
       logging::Node("content", textNode);
       logging::MsgEntry("old text '%s'",
                         NS_ConvertUTF16toUTF8(textAcc->AsTextLeaf()->Text()).get());
       logging::MsgEntry("new text: '%s'",
                         NS_ConvertUTF16toUTF8(text).get());
@@ -756,17 +756,17 @@ NotificationController::TextEnumerator(n
 #endif
 
     TextUpdater::Run(document, textAcc->AsTextLeaf(), text);
     return PL_DHASH_NEXT;
   }
 
   // Append an accessible if rendered text is not empty.
   if (!text.IsEmpty()) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eTree | logging::eText)) {
       logging::MsgBegin("TREE", "text node gains new content");
       logging::Node("container", containerElm);
       logging::Node("content", textNode);
       logging::MsgEnd();
     }
 #endif
 
--- a/accessible/src/base/NotificationController.h
+++ b/accessible/src/base/NotificationController.h
@@ -5,17 +5,17 @@
 
 #ifndef NotificationController_h_
 #define NotificationController_h_
 
 #include "AccEvent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsRefreshDriver.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 class Accessible;
 class DocAccessible;
 class nsIContent;
 
 /**
@@ -131,17 +131,17 @@ public:
    *        the notification is processed.
    */
   template<class Class, class Arg>
   inline void HandleNotification(Class* aInstance,
                                  typename TNotification<Class, Arg>::Callback aMethod,
                                  Arg* aArg)
   {
     if (!IsUpdatePending()) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
       if (mozilla::a11y::logging::IsEnabled(mozilla::a11y::logging::eNotifications))
         mozilla::a11y::logging::Text("sync notification processing");
 #endif
       (aInstance->*aMethod)(aArg);
       return;
     }
 
     nsRefPtr<Notification> notification =
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -8,17 +8,17 @@
 #include "ApplicationAccessible.h"
 #include "DocAccessible-inl.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
 #include "RootAccessibleWrap.h"
 #include "States.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
@@ -40,17 +40,17 @@ using namespace mozilla::a11y;
 
 DocAccessible*
 nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
 {
   if (!aDocument)
     return nullptr;
 
   // Ensure CacheChildren is called before we query cache.
-  nsAccessNode::GetApplicationAccessible()->EnsureChildren();
+  ApplicationAcc()->EnsureChildren();
 
   DocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
   if (docAcc)
     return docAcc;
 
   return CreateDocOrRootAccessible(aDocument);
 }
 
@@ -140,17 +140,17 @@ nsAccDocManager::OnStateChange(nsIWebPro
   nsCOMPtr<nsIDOMDocument> DOMDocument;
   DOMWindow->GetDocument(getter_AddRefs(DOMDocument));
   NS_ENSURE_STATE(DOMDocument);
 
   nsCOMPtr<nsIDocument> document(do_QueryInterface(DOMDocument));
 
   // Document was loaded.
   if (aStateFlags & STATE_STOP) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocLoad))
       logging::DocLoad("document loaded", aWebProgress, aRequest, aStateFlags);
 #endif
 
     // Figure out an event type to notify the document has been loaded.
     uint32_t eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED;
 
     // Some XUL documents get start state and then stop state with failure
@@ -169,17 +169,17 @@ nsAccDocManager::OnStateChange(nsIWebPro
         eventType = 0;
     }
 
     HandleDOMDocumentLoad(document, eventType);
     return NS_OK;
   }
 
   // Document loading was started.
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocLoad))
     logging::DocLoad("start document loading", aWebProgress, aRequest, aStateFlags);
 #endif
 
   DocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
   if (!docAcc)
     return NS_OK;
 
@@ -258,17 +258,17 @@ nsAccDocManager::HandleEvent(nsIDOMEvent
     return NS_OK;
 
   if (type.EqualsLiteral("pagehide")) {
     // 'pagehide' event is registered on every DOM document we create an
     // accessible for, process the event for the target. This document
     // accessible and all its sub document accessible are shutdown as result of
     // processing.
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocDestroy))
       logging::DocDestroy("received 'pagehide' event", document);
 #endif
 
     // Ignore 'pagehide' on temporary documents since we ignore them entirely in
     // accessibility.
     if (document->IsInitialDocument())
       return NS_OK;
@@ -284,17 +284,17 @@ nsAccDocManager::HandleEvent(nsIDOMEvent
 
     return NS_OK;
   }
 
   // XXX: handle error pages loading separately since they get neither
   // webprogress notifications nor 'pageshow' event.
   if (type.EqualsLiteral("DOMContentLoaded") &&
       nsCoreUtils::IsErrorPage(document)) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocLoad))
       logging::DocLoad("handled 'DOMContentLoaded' event", document);
 #endif
 
     HandleDOMDocumentLoad(document,
                           nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
   }
 
@@ -325,25 +325,25 @@ nsAccDocManager::AddListeners(nsIDocumen
                               bool aAddDOMContentLoadedListener)
 {
   nsPIDOMWindow *window = aDocument->GetWindow();
   nsIDOMEventTarget *target = window->GetChromeEventHandler();
   nsEventListenerManager* elm = target->GetListenerManager(true);
   elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
                               NS_EVENT_FLAG_CAPTURE);
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate))
     logging::Text("added 'pagehide' listener");
 #endif
 
   if (aAddDOMContentLoadedListener) {
     elm->AddEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
                                 NS_EVENT_FLAG_CAPTURE);
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocCreate))
       logging::Text("added 'DOMContentLoaded' listener");
 #endif
   }
 }
 
 DocAccessible*
 nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
@@ -388,36 +388,35 @@ nsAccDocManager::CreateDocOrRootAccessib
   mDocAccessibleCache.Put(aDocument, docAcc);
 
   // Initialize the document accessible.
   docAcc->Init();
   docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
 
   // Bind the document to the tree.
   if (isRootDoc) {
-    Accessible* appAcc = nsAccessNode::GetApplicationAccessible();
-    if (!appAcc->AppendChild(docAcc)) {
+    if (!ApplicationAcc()->AppendChild(docAcc)) {
       docAcc->Shutdown();
       return nullptr;
     }
 
     // Fire reorder event to notify new accessible document has been attached to
     // the tree. The reorder event is delivered after the document tree is
     // constructed because event processing and tree construction are done by
     // the same document.
     nsRefPtr<AccEvent> reorderEvent =
-      new AccEvent(nsIAccessibleEvent::EVENT_REORDER, appAcc, eAutoDetect,
-                   AccEvent::eCoalesceFromSameSubtree);
+      new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc(),
+                   eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
     docAcc->FireDelayedAccessibleEvent(reorderEvent);
 
   } else {
     parentDocAcc->BindChildDocument(docAcc);
   }
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate)) {
     logging::DocCreate("document creation finished", aDocument);
     logging::Stack();
   }
 #endif
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAccessNode.h"
 
-#include "ApplicationAccessibleWrap.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "RootAccessible.h"
 
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDOMWindow.h"
@@ -19,26 +18,24 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsFocusManager.h"
 #include "nsPresContext.h"
 #include "mozilla/Services.h"
 
 using namespace mozilla::a11y;
 
-/* For documentation of the accessibility architecture, 
+/* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
-ApplicationAccessible* nsAccessNode::gApplicationAccessible = nullptr;
-
 /*
  * Class nsAccessNode
  */
- 
+
 ////////////////////////////////////////////////////////////////////////////////
 // AccessNode. nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_1(nsAccessNode, mContent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode)
   NS_INTERFACE_MAP_ENTRY(nsAccessNode)
 NS_INTERFACE_MAP_END
@@ -77,51 +74,16 @@ void nsAccessNode::LastRelease()
 
 void
 nsAccessNode::Shutdown()
 {
   mContent = nullptr;
   mDoc = nullptr;
 }
 
-ApplicationAccessible*
-nsAccessNode::GetApplicationAccessible()
-{
-  NS_ASSERTION(!nsAccessibilityService::IsShutdown(),
-               "Accessibility wasn't initialized!");
-
-  if (!gApplicationAccessible) {
-    ApplicationAccessibleWrap::PreCreate();
-
-    gApplicationAccessible = new ApplicationAccessibleWrap();
-
-    // Addref on create. Will Release in ShutdownXPAccessibility()
-    NS_ADDREF(gApplicationAccessible);
-
-    gApplicationAccessible->Init();
-  }
-
-  return gApplicationAccessible;
-}
-
-void nsAccessNode::ShutdownXPAccessibility()
-{
-  // Called by nsAccessibilityService::Shutdown()
-  // which happens when xpcom is shutting down
-  // at exit of program
-
-  // Release gApplicationAccessible after everything else is shutdown
-  // so we don't accidently create it again while tearing down root accessibles
-  ApplicationAccessibleWrap::Unload();
-  if (gApplicationAccessible) {
-    gApplicationAccessible->Shutdown();
-    NS_RELEASE(gApplicationAccessible);
-  }
-}
-
 RootAccessible*
 nsAccessNode::RootAccessible() const
 {
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mContent);
   NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent");
   if (!docShellTreeItem) {
     return nullptr;
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -16,17 +16,16 @@
 
 class nsAccessNode;
 class DocAccessible;
 class nsIAccessibleDocument;
 class nsIContent;
 
 namespace mozilla {
 namespace a11y {
-class ApplicationAccessible;
 class RootAccessible;
 }
 }
 
 class nsIPresShell;
 class nsPresContext;
 class nsIFrame;
 class nsIDocShellTreeItem;
@@ -36,23 +35,16 @@ class nsAccessNode: public nsISupports
 public:
 
   nsAccessNode(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~nsAccessNode();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsAccessNode)
 
-  static void ShutdownXPAccessibility();
-
-  /**
-   * Return an application accessible.
-   */
-  static mozilla::a11y::ApplicationAccessible* GetApplicationAccessible();
-
   /**
    * Return the document accessible for this access node.
    */
   DocAccessible* Document() const { return mDoc; }
 
   /**
    * Return the root document accessible for this accessnode.
    */
@@ -106,14 +98,12 @@ protected:
 
   nsCOMPtr<nsIContent> mContent;
   DocAccessible* mDoc;
 
 private:
   nsAccessNode() MOZ_DELETE;
   nsAccessNode(const nsAccessNode&) MOZ_DELETE;
   nsAccessNode& operator =(const nsAccessNode&) MOZ_DELETE;
-  
-  static mozilla::a11y::ApplicationAccessible* gApplicationAccessible;
 };
 
 #endif
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -34,33 +34,32 @@
 #include "RootAccessibleWrap.h"
 #include "States.h"
 #include "Statistics.h"
 #ifdef XP_WIN
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 #include "TextLeafAccessibleWrap.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsImageFrame.h"
 #include "nsIObserverService.h"
 #include "nsLayoutUtils.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsObjectFrame.h"
-#include "mozilla/FunctionTimer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Util.h"
 
 #ifdef MOZ_XUL
 #include "XULAlertAccessible.h"
 #include "XULColorPickerAccessible.h"
@@ -77,22 +76,22 @@
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
+ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
 bool nsAccessibilityService::gIsShutdown = true;
 
 nsAccessibilityService::nsAccessibilityService() :
   nsAccDocManager(), FocusManager()
 {
-  NS_TIME_FUNCTION;
 }
 
 nsAccessibilityService::~nsAccessibilityService()
 {
   NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!");
   gAccessibilityService = nullptr;
 }
 
@@ -466,17 +465,17 @@ nsAccessibilityService::CreateHTMLCaptio
 }
 
 void
 nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
                                              nsIContent* aContainer,
                                              nsIContent* aStartChild,
                                              nsIContent* aEndChild)
 {
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eTree)) {
     logging::MsgBegin("TREE", "content inserted");
     logging::Node("container", aContainer);
     for (nsIContent* child = aStartChild; child != aEndChild;
          child = child->GetNextSibling()) {
       logging::Node("content", child);
     }
     logging::MsgEnd();
@@ -488,17 +487,17 @@ nsAccessibilityService::ContentRangeInse
     docAccessible->ContentInserted(aContainer, aStartChild, aEndChild);
 }
 
 void
 nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
                                        nsIContent* aContainer,
                                        nsIContent* aChild)
 {
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eTree)) {
     logging::MsgBegin("TREE", "content removed");
     logging::Node("container", aContainer);
     logging::Node("content", aChild);
     logging::MsgEnd();
   }
 #endif
 
@@ -597,17 +596,18 @@ nsAccessibilityService::RecreateAccessib
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleRetrieval
 
 NS_IMETHODIMP
 nsAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
 {
   NS_ENSURE_ARG_POINTER(aAccessibleApplication);
 
-  NS_IF_ADDREF(*aAccessibleApplication = nsAccessNode::GetApplicationAccessible());
+  NS_IF_ADDREF(*aAccessibleApplication = ApplicationAcc());
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
                                          nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
@@ -838,17 +838,17 @@ nsAccessibilityService::CreateAccessible
   NS_ADDREF(*aPivot = pivot);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessibilityService::SetLogging(const nsACString& aModules)
 {
-#ifdef DEBUG
+#ifdef A11Y_LOG
   logging::Enable(PromiseFlatCString(aModules));
 #endif
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService public
 
@@ -896,80 +896,69 @@ nsAccessibilityService::GetOrCreateAcces
     return nullptr;
   }
 
   if (aNode->OwnerDoc() != aDoc->GetDocumentNode()) {
     NS_ERROR("Creating accessible for wrong document");
     return nullptr;
   }
 
-  nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
-  if (!content)
+  if (!aNode->IsContent())
     return nullptr;
 
-  // Frames can be deallocated when we flush layout, or when we call into code
-  // that can flush layout, either directly, or via DOM manipulation, or some
-  // CSS styles like :hover. We use the weak frame checks to avoid calling
-  // methods on a dead frame pointer.
-  nsWeakFrame weakFrame = content->GetPrimaryFrame();
+  nsIContent* content = aNode->AsContent();
+  nsIFrame* frame = content->GetPrimaryFrame();
 
   // Check frame and its visibility. Note, hidden frame allows visible
   // elements in subtree.
-  if (!weakFrame.GetFrame() || !weakFrame->GetStyleVisibility()->IsVisible()) {
-    if (aIsSubtreeHidden && !weakFrame.GetFrame())
+  if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
+    if (aIsSubtreeHidden && !frame)
       *aIsSubtreeHidden = true;
 
     return nullptr;
   }
 
-  if (weakFrame.GetFrame()->GetContent() != content) {
+  if (frame->GetContent() != content) {
     // Not the main content for this frame. This happens because <area>
     // elements return the image frame as their primary frame. The main content
     // for the image frame is the image content. If the frame is not an image
     // frame or the node is not an area element then null is returned.
     // This setup will change when bug 135040 is fixed. Make sure we don't
     // create area accessible here. Hopefully assertion below will handle that.
 
 #ifdef DEBUG
-  nsImageFrame* imageFrame = do_QueryFrame(weakFrame.GetFrame());
+  nsImageFrame* imageFrame = do_QueryFrame(frame);
   NS_ASSERTION(imageFrame && content->IsHTML() && content->Tag() == nsGkAtoms::area,
                "Unknown case of not main content for the frame!");
 #endif
     return nullptr;
   }
 
 #ifdef DEBUG
-  nsImageFrame* imageFrame = do_QueryFrame(weakFrame.GetFrame());
+  nsImageFrame* imageFrame = do_QueryFrame(frame);
   NS_ASSERTION(!imageFrame || !content->IsHTML() || content->Tag() != nsGkAtoms::area,
                "Image map manages the area accessible creation!");
 #endif
 
-  DocAccessible* docAcc =
-    GetAccService()->GetDocAccessible(aNode->OwnerDoc());
-  if (!docAcc) {
-    NS_NOTREACHED("Node has no host document accessible!");
-    return nullptr;
-  }
-
   // Attempt to create an accessible based on what we know.
   nsRefPtr<Accessible> newAcc;
 
   // Create accessible for visible text frames.
   if (content->IsNodeOfType(nsINode::eTEXT)) {
     nsAutoString text;
-    weakFrame->GetRenderedText(&text, nullptr, nullptr, 0, PR_UINT32_MAX);
+    frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
     if (text.IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
-    newAcc = weakFrame->CreateAccessible();
-    if (docAcc->BindToDocument(newAcc, nullptr)) {
+    newAcc = frame->CreateAccessible();
+    if (aDoc->BindToDocument(newAcc, nullptr)) {
       newAcc->AsTextLeaf()->SetText(text);
       return newAcc;
     }
 
     return nullptr;
   }
 
   bool isHTML = content->IsHTML();
@@ -977,26 +966,26 @@ nsAccessibilityService::GetOrCreateAcces
     // Create hyper text accessible for HTML map if it is used to group links
     // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
     // map rect is empty then it is used for links grouping. Otherwise it should
     // be used in conjunction with HTML image element and in this case we don't
     // create any accessible for it and don't walk into it. The accessibles for
     // HTML area (HTMLAreaAccessible) the map contains are attached as
     // children of the appropriate accessible for HTML image
     // (ImageAccessible).
-    if (nsLayoutUtils::GetAllInFlowRectsUnion(weakFrame,
-                                              weakFrame->GetParent()).IsEmpty()) {
+    if (nsLayoutUtils::GetAllInFlowRectsUnion(frame,
+                                              frame->GetParent()).IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
-    newAcc = new HyperTextAccessibleWrap(content, docAcc);
-    if (docAcc->BindToDocument(newAcc, aria::GetRoleMap(aNode)))
+    newAcc = new HyperTextAccessibleWrap(content, aDoc);
+    if (aDoc->BindToDocument(newAcc, aria::GetRoleMap(aNode)))
       return newAcc;
     return nullptr;
   }
 
   nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aNode);
 
   // If the element is focusable or global ARIA attribute is applied to it or
   // it is referenced by ARIA relationship then treat role="presentation" on
@@ -1004,18 +993,18 @@ nsAccessibilityService::GetOrCreateAcces
   if (roleMapEntry && roleMapEntry->Is(nsGkAtoms::presentation)) {
     if (!content->IsFocusable() && !HasUniversalAriaProperty(content) &&
         !HasRelatedContent(content))
       return nullptr;
 
     roleMapEntry = nullptr;
   }
 
-  if (weakFrame.IsAlive() && !newAcc && isHTML) {  // HTML accessibles
-    nsIAtom *frameType = weakFrame.GetFrame()->GetType();
+  if (!newAcc && isHTML) {  // HTML accessibles
+    nsIAtom* frameType = frame->GetType();
 
     bool partOfHTMLTable =
       frameType == nsGkAtoms::tableCaptionFrame ||
       frameType == nsGkAtoms::tableCellFrame ||
       frameType == nsGkAtoms::tableRowGroupFrame ||
       frameType == nsGkAtoms::tableRowFrame;
     bool legalPartOfHTMLTable = partOfHTMLTable;
 
@@ -1078,109 +1067,102 @@ nsAccessibilityService::GetOrCreateAcces
     if (roleMapEntry) {
       // Create ARIA grid/treegrid accessibles if node is not a child or legal
       // child of HTML table and is not a HTML table.
       if ((!partOfHTMLTable || !legalPartOfHTMLTable) &&
           frameType != nsGkAtoms::tableOuterFrame) {
 
         if (roleMapEntry->role == roles::TABLE ||
             roleMapEntry->role == roles::TREE_TABLE) {
-          newAcc = new ARIAGridAccessibleWrap(content, docAcc);
+          newAcc = new ARIAGridAccessibleWrap(content, aDoc);
 
         } else if (roleMapEntry->role == roles::GRID_CELL ||
             roleMapEntry->role == roles::ROWHEADER ||
             roleMapEntry->role == roles::COLUMNHEADER) {
-          newAcc = new ARIAGridCellAccessibleWrap(content, docAcc);
+          newAcc = new ARIAGridCellAccessibleWrap(content, aDoc);
         }
       }
     }
 
     if (!newAcc) {
       // Prefer to use markup (mostly tag name, perhaps attributes) to
       // decide if and what kind of accessible to create.
       // The method creates accessibles for table related content too therefore
       // we do not call it if accessibles for table related content are
       // prevented above.
-      newAcc = CreateHTMLAccessibleByMarkup(weakFrame.GetFrame(), content,
-                                            docAcc, legalPartOfHTMLTable);
+      newAcc = CreateHTMLAccessibleByMarkup(frame, content, aDoc,
+                                            legalPartOfHTMLTable);
 
       if (!newAcc && (!partOfHTMLTable || legalPartOfHTMLTable)) {
         // Do not create accessible object subtrees for non-rendered table
         // captions. This could not be done in
         // nsTableCaptionFrame::GetAccessible() because the descendants of
         // the table caption would still be created. By setting
         // *aIsSubtreeHidden = true we ensure that no descendant accessibles
         // are created.
-        nsIFrame* f = weakFrame.GetFrame();
-        if (!f) {
-          f = aDoc->PresShell()->GetRealPrimaryFrameFor(content);
-        }
-        if (f->GetType() == nsGkAtoms::tableCaptionFrame &&
-           f->GetRect().IsEmpty()) {
+        if (frame->GetType() == nsGkAtoms::tableCaptionFrame &&
+            frame->GetRect().IsEmpty()) {
           // XXX This is not the ideal place for this code, but right now there
           // is no better place:
           if (aIsSubtreeHidden)
             *aIsSubtreeHidden = true;
 
           return nullptr;
         }
 
         // Try using frame to do it.
-        newAcc = f->CreateAccessible();
+        newAcc = frame->CreateAccessible();
       }
     }
   }
 
   if (!newAcc) {
     // Elements may implement nsIAccessibleProvider via XBL. This allows them to
     // say what kind of accessible to create.
-    newAcc = CreateAccessibleByType(content, docAcc);
+    newAcc = CreateAccessibleByType(content, aDoc);
   }
 
   if (!newAcc) {
     // xul:deck does not have XBL and nsIFrame::CreateAccessible() is only called 
     // on HTML elements
     nsIAtom* tag = content->Tag();
     if ((tag == nsGkAtoms::deck) || (tag == nsGkAtoms::tabpanels)) {
-      newAcc = new XULDeckAccessible(content, docAcc);
+      newAcc = new XULDeckAccessible(content, aDoc);
     } else if (content->IsSVG(nsGkAtoms::svg)) {
-      newAcc = new EnumRoleAccessible(content, docAcc, roles::DIAGRAM);
+      newAcc = new EnumRoleAccessible(content, aDoc, roles::DIAGRAM);
     } else if (content->IsMathML(nsGkAtoms::math)) {
-      newAcc = new EnumRoleAccessible(content, docAcc, roles::EQUATION);
+      newAcc = new EnumRoleAccessible(content, aDoc, roles::EQUATION);
     }
   }
 
-  if (!newAcc) {
-    newAcc = CreateAccessibleForDeckChild(weakFrame.GetFrame(), content,
-                                          docAcc);
-  }
+  if (!newAcc)
+    newAcc = CreateAccessibleForDeckChild(frame, content, aDoc);
 
   // If no accessible, see if we need to create a generic accessible because
   // of some property that makes this object interesting
   // We don't do this for <body>, <html>, <window>, <dialog> etc. which
   // correspond to the doc accessible and will be created in any case
   if (!newAcc && content->Tag() != nsGkAtoms::body && content->GetParent() &&
-      ((weakFrame.GetFrame() && weakFrame.GetFrame()->IsFocusable()) ||
+      (frame->IsFocusable() ||
        (isHTML && nsCoreUtils::HasClickListener(content)) ||
        HasUniversalAriaProperty(content) || roleMapEntry ||
        HasRelatedContent(content) || nsCoreUtils::IsXLink(content))) {
     // This content is focusable or has an interesting dynamic content accessibility property.
     // If it's interesting we need it in the accessibility hierarchy so that events or
     // other accessibles can point to it, or so that it can hold a state, etc.
     if (isHTML) {
       // Interesting HTML container which may have selectable text and/or embedded objects
-      newAcc = new HyperTextAccessibleWrap(content, docAcc);
-    }
-    else {  // XUL, SVG, MathML etc.
+      newAcc = new HyperTextAccessibleWrap(content, aDoc);
+    } else {  // XUL, SVG, MathML etc.
       // Interesting generic non-HTML container
-      newAcc = new AccessibleWrap(content, docAcc);
+      newAcc = new AccessibleWrap(content, aDoc);
     }
   }
 
-  return docAcc->BindToDocument(newAcc, roleMapEntry) ? newAcc : nullptr;
+  return aDoc->BindToDocument(newAcc, roleMapEntry) ? newAcc : nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService private
 
 bool
 nsAccessibilityService::Init()
 {
@@ -1194,20 +1176,26 @@ nsAccessibilityService::Init()
   if (!observerService)
     return false;
 
   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   static const PRUnichar kInitIndicator[] = { '1', 0 };
   observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kInitIndicator);
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   logging::CheckEnv();
 #endif
 
+  // Create and initialize the application accessible.
+  ApplicationAccessibleWrap::PreCreate();
+  gApplicationAccessible = new ApplicationAccessibleWrap();
+  NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
+  gApplicationAccessible->Init();
+
   // Initialize accessibility.
   nsAccessNodeWrap::InitAccessibility();
 
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::
     AnnotateCrashReport(NS_LITERAL_CSTRING("Accessibility"),
                         NS_LITERAL_CSTRING("Active"));
 #endif
@@ -1237,16 +1225,21 @@ nsAccessibilityService::Shutdown()
   // Don't null accessibility service static member at this point to be safe
   // if someone will try to operate with it.
 
   NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
 
   gIsShutdown = true;
 
   nsAccessNodeWrap::ShutdownAccessibility();
+
+  ApplicationAccessibleWrap::Unload();
+  gApplicationAccessible->Shutdown();
+  NS_RELEASE(gApplicationAccessible);
+  gApplicationAccessible = nullptr;
 }
 
 bool
 nsAccessibilityService::HasUniversalAriaProperty(nsIContent *aContent)
 {
   // ARIA attributes that take token values (NMTOKEN, bool) are special cased
   // because of special value "undefined" (see HasDefinedARIAToken).
   return nsAccUtils::HasDefinedARIAToken(aContent, nsGkAtoms::aria_atomic) ||
@@ -1277,17 +1270,17 @@ nsAccessibilityService::CreateAccessible
 
   int32_t type;
   nsresult rv = accessibleProvider->GetAccessibleType(&type);
   if (NS_FAILED(rv))
     return nullptr;
 
   if (type == nsIAccessibleProvider::OuterDoc) {
     Accessible* accessible = new OuterDocAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   Accessible* accessible = nullptr;
   switch (type)
   {
 #ifdef MOZ_XUL
     case nsIAccessibleProvider::NoAccessible:
@@ -1557,128 +1550,127 @@ nsAccessibilityService::CreateHTMLAccess
                                                      nsIContent* aContent,
                                                      DocAccessible* aDoc,
                                                      bool aIsLegalPartOfHTMLTable)
 {
   if (aIsLegalPartOfHTMLTable) {
     if (nsCoreUtils::IsHTMLTableHeader(aContent)) {
       Accessible* accessible =
         new HTMLTableHeaderCellAccessibleWrap(aContent, aDoc);
-      NS_IF_ADDREF(accessible);
+      NS_ADDREF(accessible);
       return accessible;
     }
 
     return nullptr;
   }
 
   // This method assumes we're in an HTML namespace.
   nsIAtom* tag = aContent->Tag();
   if (tag == nsGkAtoms::figcaption) {
     Accessible* accessible = new HTMLFigcaptionAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::figure) {
     Accessible* accessible = new HTMLFigureAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::legend) {
     Accessible* accessible = new HTMLLegendAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::option) {
     Accessible* accessible = new HTMLSelectOptionAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::optgroup) {
     Accessible* accessible = new HTMLSelectOptGroupAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::ul || tag == nsGkAtoms::ol ||
       tag == nsGkAtoms::dl) {
     Accessible* accessible = new HTMLListAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::a) {
     // Only some roles truly enjoy life as HTMLLinkAccessibles, for details
     // see closed bug 494807.
     nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent);
     if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
         roleMapEntry->role != roles::LINK) {
       Accessible* accessible = new HyperTextAccessibleWrap(aContent, aDoc);
-      NS_IF_ADDREF(accessible);
+      NS_ADDREF(accessible);
       return accessible;
     }
 
     Accessible* accessible = new HTMLLinkAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::dt || tag == nsGkAtoms::li) {
     // Create list item accessible unconditionally by tag name. nsBlockFrame
     // creates the list item accessible for other elements styled as list items.
     Accessible* accessible = new HTMLLIAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::abbr ||
       tag == nsGkAtoms::acronym ||
       tag == nsGkAtoms::blockquote ||
       tag == nsGkAtoms::dd ||
       tag == nsGkAtoms::form ||
       tag == nsGkAtoms::h1 ||
       tag == nsGkAtoms::h2 ||
       tag == nsGkAtoms::h3 ||
       tag == nsGkAtoms::h4 ||
       tag == nsGkAtoms::h5 ||
       tag == nsGkAtoms::h6 ||
       tag == nsGkAtoms::q) {
     Accessible* accessible = new HyperTextAccessibleWrap(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::output) {
     Accessible* accessible = new HTMLOutputAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::progress) {
     Accessible* accessible =
       new HTMLProgressMeterAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   return nullptr;
  }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibilityService (DON'T put methods here)
 
 Accessible*
 nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
-  ApplicationAccessible* applicationAcc =
-    nsAccessNode::GetApplicationAccessible();
+  ApplicationAccessible* applicationAcc = ApplicationAcc();
   if (!applicationAcc)
     return nullptr;
 
   nsRefPtr<NativeRootAccessibleWrap> nativeRootAcc =
     new NativeRootAccessibleWrap(static_cast<AtkObject*>(aAtkAccessible));
   if (!nativeRootAcc)
     return nullptr;
 
@@ -1688,18 +1680,17 @@ nsAccessibilityService::AddNativeRootAcc
 
   return nullptr;
 }
 
 void
 nsAccessibilityService::RemoveNativeRootAccessible(Accessible* aAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
-  ApplicationAccessible* applicationAcc =
-    nsAccessNode::GetApplicationAccessible();
+  ApplicationAccessible* applicationAcc = ApplicationAcc();
 
   if (applicationAcc)
     applicationAcc->RemoveChild(aAccessible);
 #endif
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NS_GetAccessibilityService
@@ -1745,28 +1736,28 @@ nsAccessibilityService::CreateAccessible
 {
   if (aFrame->GetType() == nsGkAtoms::boxFrame ||
       aFrame->GetType() == nsGkAtoms::scrollFrame) {
 
     nsIFrame* parentFrame = aFrame->GetParent();
     if (parentFrame && parentFrame->GetType() == nsGkAtoms::deckFrame) {
       // If deck frame is for xul:tabpanels element then the given node has
       // tabpanel accessible.
-      nsCOMPtr<nsIContent> parentContent = parentFrame->GetContent();
+      nsIContent* parentContent = parentFrame->GetContent();
 #ifdef MOZ_XUL
       if (parentContent->NodeInfo()->Equals(nsGkAtoms::tabpanels,
                                             kNameSpaceID_XUL)) {
         Accessible* accessible = new XULTabpanelAccessible(aContent, aDoc);
-        NS_IF_ADDREF(accessible);
+        NS_ADDREF(accessible);
         return accessible;
       }
 #endif
       Accessible* accessible = new EnumRoleAccessible(aContent, aDoc,
                                                       roles::PROPERTYPAGE);
-      NS_IF_ADDREF(accessible);
+      NS_ADDREF(accessible);
       return accessible;
     }
   }
 
   return nullptr;
 }
 
 #ifdef MOZ_XUL
@@ -1784,23 +1775,23 @@ nsAccessibilityService::CreateAccessible
     return nullptr;
 
   int32_t count = 0;
   treeColumns->GetCount(&count);
 
   // Outline of list accessible.
   if (count == 1) {
     Accessible* accessible = new XULTreeAccessible(aContent, aDoc);
-    NS_IF_ADDREF(accessible);
+    NS_ADDREF(accessible);
     return accessible;
   }
 
   // Table or tree table accessible.
   Accessible* accessible = new XULTreeGridAccessibleWrap(aContent, aDoc);
-  NS_IF_ADDREF(accessible);
+  NS_ADDREF(accessible);
   return accessible;
 }
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // Services
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -1808,16 +1799,22 @@ namespace mozilla {
 namespace a11y {
 
 FocusManager*
 FocusMgr()
 {
   return nsAccessibilityService::gAccessibilityService;
 }
 
+ApplicationAccessible*
+ApplicationAcc()
+{
+  return nsAccessibilityService::gApplicationAccessible;
+}
+
 EPlatformDisabledState
 PlatformDisabledState()
 {
   static int disabledState = 0xff;
 
   if (disabledState == 0xff) {
     disabledState = Preferences::GetInt("accessibility.force_disabled", 0);
     if (disabledState < ePlatformIsForceEnabled)
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -16,32 +16,39 @@
 #include "nsIObserver.h"
 
 class nsImageFrame;
 class nsITreeView;
 
 namespace mozilla {
 namespace a11y {
 
+class ApplicationAccessible;
+
 /**
  * Return focus manager.
  */
 FocusManager* FocusMgr();
 
 enum EPlatformDisabledState {
   ePlatformIsForceEnabled = -1,
   ePlatformIsEnabled = 0,
   ePlatformIsDisabled = 1
 };
 
 /**
  * Return the platform disabled state.
  */
 EPlatformDisabledState PlatformDisabledState();
 
+/**
+ * Returns the application accessible.
+ */
+ApplicationAccessible* ApplicationAcc();
+
 #ifdef MOZ_ACCESSIBILITY_ATK
 /**
  * Perform initialization that should be done as soon as possible, in order
  * to minimize startup time.
  * XXX: this function and the next defined in ApplicationAccessibleWrap.cpp
  */
 void PreInit();
 #endif
@@ -248,31 +255,37 @@ private:
 #endif
 
   /**
    * Reference for accessibility service instance.
    */
   static nsAccessibilityService* gAccessibilityService;
 
   /**
+   * Reference for application accessible instance.
+   */
+  static mozilla::a11y::ApplicationAccessible* gApplicationAccessible;
+
+  /**
    * Indicates whether accessibility service was shutdown.
    */
   static bool gIsShutdown;
 
   /**
    * Does this content node have a universal ARIA property set on it?
    * A universal ARIA property is one that can be defined on any element even if there is no role.
    *
    * @param aContent The content node to test
    * @return true if there is a universal ARIA property set on the node
    */
   bool HasUniversalAriaProperty(nsIContent *aContent);
 
   friend nsAccessibilityService* GetAccService();
   friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr();
+  friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc();
 
   friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
 };
 
 /**
  * Return the accessibility service instance. (Handy global function)
  */
 inline nsAccessibilityService*
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -90,20 +90,18 @@ nsCaretAccessible::SetControlSelectionLi
   mLastTextAccessible = nullptr;
 
   // When focus moves such that the caret is part of a new frame selection
   // this removes the old selection listener and attaches a new one for
   // the current focus.
 
   nsCOMPtr<nsISelectionController> controller =
     GetSelectionControllerForNode(mCurrentControl);
-#ifdef DEBUG
   NS_ASSERTION(controller || aCurrentNode->IsNodeOfType(nsINode::eDOCUMENT),
                "No selection controller for non document node!");
-#endif
   if (!controller)
     return NS_OK;
 
   // Register 'this' as selection listener for the normal selection.
   nsCOMPtr<nsISelection> normalSel;
   controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
                            getter_AddRefs(normalSel));
   nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
@@ -175,17 +173,17 @@ nsCaretAccessible::NotifySelectionChange
                                           int16_t aReason)
 {
   NS_ENSURE_ARG(aDOMDocument);
   NS_ENSURE_STATE(mRootAccessible);
 
   nsCOMPtr<nsIDocument> documentNode(do_QueryInterface(aDOMDocument));
   DocAccessible* document = GetAccService()->GetDocAccessible(documentNode);
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eSelection))
     logging::SelChange(aSelection, document);
 #endif
 
   // Don't fire events until document is loaded.
   if (document && document->IsContentLoaded()) {
     // The caret accessible has the same lifetime as the root accessible, and
     // this outlives all its descendant document accessibles, so that we are
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -612,27 +612,43 @@ Accessible::VisibilityState()
     return states::INVISIBLE;
 
   // Walk the parent frame chain to see if there's invisible parent or the frame
   // is in background tab.
   if (!frame->GetStyleVisibility()->IsVisible())
     return states::INVISIBLE;
 
   nsIFrame* curFrame = frame;
+  nsPoint framePos(0, 0);
   do {
     nsIView* view = curFrame->GetView();
     if (view && view->GetVisibility() == nsViewVisibility_kHide)
       return states::INVISIBLE;
 
     // Offscreen state for background tab content.
     nsIFrame* parentFrame = curFrame->GetParent();
     nsDeckFrame* deckFrame = do_QueryFrame(parentFrame);
     if (deckFrame && deckFrame->GetSelectedBox() != curFrame)
       return states::OFFSCREEN;
 
+    // If contained by scrollable frame then check that at least 12 pixels
+    // around the object is visible, otherwise the object is offscreen.
+    framePos += curFrame->GetPosition();
+    nsIScrollableFrame* scrollableFrame = do_QueryFrame(parentFrame);
+    if (scrollableFrame) {
+      nsRect scrollPortRect = scrollableFrame->GetScrollPortRect();
+      nsRect frameRect(framePos, frame->GetSize());
+      if (!scrollPortRect.Contains(frameRect)) {
+        const nscoord kMinPixels = nsPresContext::CSSPixelsToAppUnits(12);
+        scrollPortRect.Deflate(kMinPixels, kMinPixels);
+        if (!scrollPortRect.Intersects(frameRect))
+          return states::OFFSCREEN;
+      }
+    }
+
     if (!parentFrame) {
       parentFrame = nsLayoutUtils::GetCrossDocParentFrame(curFrame);
       if (parentFrame && !parentFrame->GetStyleVisibility()->IsVisible())
         return states::INVISIBLE;
     }
 
     curFrame = parentFrame;
   } while (curFrame);
@@ -646,27 +662,16 @@ Accessible::VisibilityState()
       !(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
       frame->GetRect().IsEmpty()) {
     nsAutoString renderedText;
     frame->GetRenderedText(&renderedText, nullptr, nullptr, 0, 1);
     if (renderedText.IsEmpty())
       return states::INVISIBLE;
   }
 
-  // We need to know if at least a kMinPixels around the object is visible,
-  // otherwise it will be marked states::OFFSCREEN.
-  const uint16_t kMinPixels  = 12;
-  const nsSize frameSize = frame->GetSize();
-  const nsRectVisibility rectVisibility =
-    mDoc->PresShell()->GetRectVisibility(frame, nsRect(nsPoint(0,0), frameSize),
-                                         nsPresContext::CSSPixelsToAppUnits(kMinPixels));
-
-  if (rectVisibility != nsRectVisibility_kVisible)
-    return states::OFFSCREEN;
-
   return 0;
 }
 
 uint64_t
 Accessible::NativeState()
 {
   uint64_t state = 0;
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -447,17 +447,17 @@ public:
    *
    * @param aText         [in] returned text of the accessible
    * @param aStartOffset  [in, optional] start offset inside of the accessible,
    *                        if missed entire text is appended
    * @param aLength       [in, optional] required length of text, if missed
    *                        then text form start offset till the end is appended
    */
   virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
-                            uint32_t aLength = PR_UINT32_MAX);
+                            uint32_t aLength = UINT32_MAX);
 
   /**
    * Assert if child not in parent's cache if the cache was initialized at this
    * point.
    */
   void TestChildCache(Accessible* aCachedChild) const;
 
   /**
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -40,17 +40,17 @@
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/Element.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif
 
 using namespace mozilla;
@@ -602,17 +602,17 @@ DocAccessible::GetAccessible(nsINode* aN
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 void
 DocAccessible::Init()
 {
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate))
     logging::DocCreate("document initialize", mDocument, this);
 #endif
 
   // Initialize notification controller.
   mNotificationController = new NotificationController(this, mPresShell);
 
   // Mark the document accessible as loaded if its DOM document was loaded at
@@ -625,17 +625,17 @@ DocAccessible::Init()
 }
 
 void
 DocAccessible::Shutdown()
 {
   if (!mPresShell) // already shutdown
     return;
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy))
     logging::DocDestroy("document shutdown", mDocument, this);
 #endif
 
   mPresShell->SetAccDocument(nullptr);
 
   if (mNotificationController) {
     mNotificationController->Shutdown();
@@ -851,17 +851,17 @@ void
 DocAccessible::AddScrollListener()
 {
   if (!mPresShell)
     return;
 
   nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollableExternal();
   if (sf) {
     sf->AddScrollPositionListener(this);
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocCreate))
       logging::Text("add scroll listener");
 #endif
   }
 }
 
 // DocAccessible protected member
 void
@@ -1225,18 +1225,21 @@ DocAccessible::ARIAActiveDescendantChang
   if (widget && widget->IsActiveWidget()) {
     nsAutoString id;
     if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
       dom::Element* activeDescendantElm = aElm->OwnerDoc()->GetElementById(id);
       if (activeDescendantElm) {
         Accessible* activeDescendant = GetAccessible(activeDescendantElm);
         if (activeDescendant) {
           FocusMgr()->ActiveItemChanged(activeDescendant, false);
-          A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("ARIA activedescedant changed",
-                                                 activeDescendant)
+#ifdef A11Y_LOG
+          if (logging::IsEnabled(logging::eFocus))
+            logging::ActiveItemChangeCausedBy("ARIA activedescedant changed",
+                                              activeDescendant);
+#endif
         }
       }
     }
   }
 }
 
 void
 DocAccessible::ContentAppended(nsIDocument* aDocument,
@@ -1310,17 +1313,17 @@ void
 DocAccessible::ParentChainChanged(nsIContent* aContent)
 {
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 nsresult
 DocAccessible::HandleAccEvent(AccEvent* aEvent)
 {
   if (logging::IsEnabled(logging::eDocLoad))
     logging::DocLoadEventHandled(aEvent);
 
   return HyperTextAccessible::HandleAccEvent(aEvent);
 }
@@ -1408,17 +1411,20 @@ DocAccessible::UnbindFromDocument(Access
 {
   NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
                "Unbinding the unbound accessible!");
 
   // Fire focus event on accessible having DOM focus if active item was removed
   // from the tree.
   if (FocusMgr()->IsActiveItem(aAccessible)) {
     FocusMgr()->ActiveItemChanged(nullptr);
-    A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("tree shutdown", aAccessible)
+#ifdef A11Y_LOG
+          if (logging::IsEnabled(logging::eFocus))
+            logging::ActiveItemChangeCausedBy("tree shutdown", aAccessible);
+#endif
   }
 
   // Remove an accessible from node-to-accessible map if it exists there.
   if (aAccessible->IsPrimaryForNode() &&
       mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
     mNodeToAccessibleMap.Remove(aAccessible->GetNode());
 
   void* uniqueID = aAccessible->UniqueID();
@@ -1753,17 +1759,17 @@ DocAccessible::FireDelayedAccessibleEven
 }
 
 // DocAccessible public member
 nsresult
 DocAccessible::FireDelayedAccessibleEvent(AccEvent* aEvent)
 {
   NS_ENSURE_ARG(aEvent);
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocLoad))
     logging::DocLoadEventFired(aEvent);
 #endif
 
   if (mNotificationController)
     mNotificationController->QueueEvent(aEvent);
 
   return NS_OK;
@@ -1844,17 +1850,17 @@ DocAccessible::ProcessContentInserted(Ac
 void
 DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
                           bool aIsInsert)
 {
   uint32_t updateFlags = eNoAccessible;
 
   // If child node is not accessible then look for its accessible children.
   Accessible* child = GetAccessible(aChildNode);
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eTree)) {
     logging::MsgBegin("TREE", "process content %s",
                       (aIsInsert ? "insertion" : "removal"));
     logging::Node("container", aContainer->GetNode());
     logging::Node("child", aChildNode);
     if (child)
       logging::Address("child", child);
     else
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -92,17 +92,17 @@ public:
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
   virtual bool NativelyUnavailable() const;
   virtual void ApplyARIAState(uint64_t* aState) const;
 
   virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
 #endif
 
   virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
 
   // HyperTextAccessible
   virtual already_AddRefed<nsIEditor> GetEditor() const;
 
--- a/accessible/src/generic/Makefile.in
+++ b/accessible/src/generic/Makefile.in
@@ -69,8 +69,12 @@ LOCAL_INCLUDES += \
   $(NULL)
 else
 LOCAL_INCLUDES += \
   -I$(srcdir)/../other \
   $(NULL)
 endif
 endif
 endif
+
+ifneq ($(A11Y_LOG),0)
+  DEFINES += -DA11Y_LOG
+endif
--- a/accessible/src/generic/OuterDocAccessible.cpp
+++ b/accessible/src/generic/OuterDocAccessible.cpp
@@ -5,17 +5,17 @@
 
 #include "OuterDocAccessible.h"
 
 #include "nsAccUtils.h"
 #include "DocAccessible.h"
 #include "Role.h"
 #include "States.h"
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // OuterDocAccessible
@@ -118,24 +118,24 @@ OuterDocAccessible::DoAction(uint8_t aIn
 
 void
 OuterDocAccessible::Shutdown()
 {
   // XXX: sometimes outerdoc accessible is shutdown because of layout style
   // change however the presshell of underlying document isn't destroyed and
   // the document doesn't get pagehide events. Shutdown underlying document if
   // any to avoid hanging document accessible.
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy))
     logging::OuterDocDestroy(this);
 #endif
 
   Accessible* childAcc = mChildren.SafeElementAt(0, nullptr);
   if (childAcc) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocDestroy)) {
       logging::DocDestroy("outerdoc's child document shutdown",
                           childAcc->GetDocumentNode());
     }
 #endif
     childAcc->Shutdown();
   }
 
@@ -169,17 +169,17 @@ OuterDocAccessible::AppendChild(Accessib
   // The old viewer will be destroyed after the new one is created.
   // For a11y, it should be safe to shut down the old document now.
   if (mChildren.Length())
     mChildren[0]->Shutdown();
 
   if (!AccessibleWrap::AppendChild(aAccessible))
     return false;
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate)) {
     logging::DocCreate("append document to outerdoc",
                        aAccessible->GetDocumentNode());
     logging::Address("outerdoc", this);
   }
 #endif
 
   return true;
@@ -189,17 +189,17 @@ bool
 OuterDocAccessible::RemoveChild(Accessible* aAccessible)
 {
   Accessible* child = mChildren.SafeElementAt(0, nullptr);
   if (child != aAccessible) {
     NS_ERROR("Wrong child to remove!");
     return false;
   }
 
-#ifdef DEBUG
+#ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocDestroy)) {
     logging::DocDestroy("remove document from outerdoc", child->GetDocumentNode(),
                         child->AsDoc());
     logging::Address("outerdoc", this);
   }
 #endif
 
   bool wasRemoved = AccessibleWrap::RemoveChild(child);
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -257,17 +257,17 @@ RootAccessible::HandleEvent(nsIDOMEvent*
   nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget));
   if (!origTargetNode)
     return NS_OK;
 
   DocAccessible* document =
     GetAccService()->GetDocAccessible(origTargetNode->OwnerDoc());
 
   if (document) {
-#ifdef DEBUG
+#ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDOMEvents)) {
       nsAutoString eventType;
       aDOMEvent->GetType(eventType);
 
       logging::MsgBegin("DOMEvents", "event '%s' handled",
                         NS_ConvertUTF16toUTF8(eventType).get());
       logging::Node("target", origTargetNode);
       logging::MsgEnd();
@@ -337,17 +337,20 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
     bool isEnabled = (state & (states::CHECKED | states::SELECTED)) != 0;
 
     nsRefPtr<AccEvent> accEvent =
       new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
     nsEventShell::FireEvent(accEvent);
 
     if (isEnabled) {
       FocusMgr()->ActiveItemChanged(accessible);
-      A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("RadioStateChange", accessible)
+#ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eFocus))
+        logging::ActiveItemChangeCausedBy("RadioStateChange", accessible);
+#endif
     }
 
     return;
   }
 
   if (eventType.EqualsLiteral("CheckboxStateChange")) {
     uint64_t state = accessible->State();
 
@@ -416,52 +419,64 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
   else if (eventType.EqualsLiteral("DOMMenuInactive")) {
     if (accessible->Role() == roles::MENUPOPUP) {
       nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
                               accessible);
     }
   }
   else if (eventType.EqualsLiteral("DOMMenuItemActive")) {
     FocusMgr()->ActiveItemChanged(accessible);
-    A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("DOMMenuItemActive", accessible)
+#ifdef A11Y_LOG
+    if (logging::IsEnabled(logging::eFocus))
+      logging::ActiveItemChangeCausedBy("DOMMenuItemActive", accessible);
+#endif
   }
   else if (eventType.EqualsLiteral("DOMMenuItemInactive")) {
     // Process DOMMenuItemInactive event for autocomplete only because this is
     // unique widget that may acquire focus from autocomplete popup while popup
     // stays open and has no active item. In case of XUL tree autocomplete
     // popup this event is fired for tree accessible.
     Accessible* widget =
       accessible->IsWidget() ? accessible : accessible->ContainerWidget();
     if (widget && widget->IsAutoCompletePopup()) {
       FocusMgr()->ActiveItemChanged(nullptr);
-      A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("DOMMenuItemInactive", accessible)
+#ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eFocus))
+        logging::ActiveItemChangeCausedBy("DOMMenuItemInactive", accessible);
+#endif
     }
   }
   else if (eventType.EqualsLiteral("DOMMenuBarActive")) {  // Always from user input
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START,
                             accessible, eFromUserInput);
 
     // Notify of active item change when menubar gets active and if it has
     // current item. This is a case of mouseover (set current menuitem) and
     // mouse click (activate the menubar). If menubar doesn't have current item
     // (can be a case of menubar activation from keyboard) then ignore this
     // notification because later we'll receive DOMMenuItemActive event after
     // current menuitem is set.
     Accessible* activeItem = accessible->CurrentItem();
     if (activeItem) {
       FocusMgr()->ActiveItemChanged(activeItem);
-      A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("DOMMenuBarActive", accessible)
+#ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eFocus))
+        logging::ActiveItemChangeCausedBy("DOMMenuBarActive", accessible);
+#endif
     }
   }
   else if (eventType.EqualsLiteral("DOMMenuBarInactive")) {  // Always from user input
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END,
                             accessible, eFromUserInput);
 
     FocusMgr()->ActiveItemChanged(nullptr);
-    A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("DOMMenuBarInactive", accessible)
+#ifdef A11Y_LOG
+    if (logging::IsEnabled(logging::eFocus))
+      logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
+#endif
   }
   else if (eventType.EqualsLiteral("ValueChange")) {
     targetDocument->
       FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
                                  targetNode, AccEvent::eRemoveDupes);
   }
 #ifdef DEBUG_DRAGDROPSTART
   else if (eventType.EqualsLiteral("mouseover")) {
@@ -642,17 +657,20 @@ RootAccessible::HandlePopupHidingEvent(n
     // For menubars processing we listen DOMMenubarActive/Inactive
     // notifications.
     notifyOf = kNotifyOfFocus;
   }
 
   // Restore focus to where it was.
   if (notifyOf & kNotifyOfFocus) {
     FocusMgr()->ActiveItemChanged(nullptr);
-    A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("popuphiding", popup)
+#ifdef A11Y_LOG
+    if (logging::IsEnabled(logging::eFocus))
+      logging::ActiveItemChangeCausedBy("popuphiding", popup);
+#endif
   }
 
   // Fire expanded state change event.
   if (notifyOf & kNotifyOfState) {
     nsRefPtr<AccEvent> event =
       new AccStateChangeEvent(widget, states::EXPANDED, false);
     document->FireDelayedAccessibleEvent(event);
   }
--- a/accessible/src/generic/TextLeafAccessible.h
+++ b/accessible/src/generic/TextLeafAccessible.h
@@ -18,17 +18,17 @@ class TextLeafAccessible : public Linkab
 {
 public:
   TextLeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~TextLeafAccessible();
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
-                            uint32_t aLength = PR_UINT32_MAX);
+                            uint32_t aLength = UINT32_MAX);
   virtual ENameValueFlag Name(nsString& aName);
 
   // TextLeafAccessible
   void SetText(const nsAString& aText) { mText = aText; }
   const nsString& Text() const { return mText; }
 
 protected:
   // Accessible
--- a/accessible/src/html/HTMLListAccessible.cpp
+++ b/accessible/src/html/HTMLListAccessible.cpp
@@ -163,17 +163,16 @@ HTMLListBulletAccessible::GetFrame() con
 
 ENameValueFlag
 HTMLListBulletAccessible::Name(nsString &aName)
 {
   aName.Truncate();
 
   // Native anonymous content, ARIA can't be used. Get list bullet text.
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
-  NS_ASSERTION(blockFrame, "No frame for list item!");
   if (blockFrame) {
     blockFrame->GetBulletText(aName);
 
     // Append space otherwise bullets are jammed up against list text.
     aName.Append(' ');
   }
 
   return eNameOK;
@@ -192,17 +191,16 @@ HTMLListBulletAccessible::NativeState()
 }
 
 void
 HTMLListBulletAccessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset,
                                        uint32_t aLength)
 {
   nsAutoString bulletText;
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
-  NS_ASSERTION(blockFrame, "No frame for list item!");
   if (blockFrame)
     blockFrame->GetBulletText(bulletText);
 
   aText.Append(Substring(bulletText, aStartOffset, aLength));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLListBulletAccessible: public
--- a/accessible/src/html/HTMLListAccessible.h
+++ b/accessible/src/html/HTMLListAccessible.h
@@ -81,17 +81,17 @@ public:
   // nsAccessNode
   virtual nsIFrame* GetFrame() const;
 
   // Accessible
   virtual ENameValueFlag Name(nsString& aName);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
-                            uint32_t aLength = PR_UINT32_MAX);
+                            uint32_t aLength = UINT32_MAX);
 
   // HTMLListBulletAccessible
 
   /**
    * Return true if the bullet is inside of list item element boundaries.
    */
   bool IsInside() const;
 };
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -58,8 +58,12 @@ LOCAL_INCLUDES += \
   $(NULL)
 else
 LOCAL_INCLUDES += \
   -I$(srcdir)/../other \
   $(NULL)
 endif
 endif
 endif
+
+ifneq ($(A11Y_LOG),0)
+  DEFINES += -DA11Y_LOG
+endif
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -7,486 +7,477 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 var EXPORTED_SYMBOLS = ['AccessFu'];
 
 Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/Geometry.jsm');
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
-Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
 Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
 
 const ACCESSFU_DISABLE = 0;
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
 var AccessFu = {
   /**
-   * Attach chrome-layer accessibility functionality to the given chrome window.
-   * If accessibility is enabled on the platform (currently Android-only), then
-   * a special accessibility mode is started (see startup()).
-   * @param {ChromeWindow} aWindow Chrome window to attach to.
-   * @param {boolean} aForceEnabled Skip platform accessibility check and enable
-   *  AccessFu.
+   * Initialize chrome-layer accessibility functionality.
+   * If accessibility is enabled on the platform, then a special accessibility
+   * mode is started.
    */
   attach: function attach(aWindow) {
     if (this.chromeWin)
       // XXX: only supports attaching to one window now.
       throw new Error('Only one window could be attached to AccessFu');
 
     Logger.info('attach');
     this.chromeWin = aWindow;
-    this.presenters = [];
 
     this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
       .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
     this.prefsBranch.addObserver('activate', this, false);
-    this.prefsBranch.addObserver('explorebytouch', this, false);
 
     this.touchAdapter = TouchAdapter;
 
-    switch(Utils.MozBuildApp) {
+    switch (Utils.MozBuildApp) {
       case 'mobile/android':
         Services.obs.addObserver(this, 'Accessibility:Settings', false);
-        Services.obs.addObserver(this, 'Accessibility:NextObject', false);
-        Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
-        Services.obs.addObserver(this, 'Accessibility:CurrentObject', false);
+        Cc['@mozilla.org/android/bridge;1'].
+          getService(Ci.nsIAndroidBridge).handleGeckoMessage(
+            JSON.stringify({ gecko: { type: 'Accessibility:Ready' } }));
         this.touchAdapter = AndroidTouchAdapter;
         break;
       case 'b2g':
         aWindow.addEventListener(
           'ContentStart',
           (function(event) {
              let content = aWindow.shell.contentBrowser.contentWindow;
              content.addEventListener('mozContentEvent', this, false, true);
            }).bind(this), false);
         break;
       default:
         break;
     }
 
-    this._processPreferences();
+    try {
+      this._activatePref = this.prefsBranch.getIntPref('activate');
+    } catch (x) {
+      this._activatePref = ACCESSFU_DISABLE;
+    }
+
+    this._enableOrDisable();
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
    * with arrow keys.
    */
   _enable: function _enable() {
     if (this._enabled)
       return;
     this._enabled = true;
 
     Logger.info('enable');
 
+    for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
+      this._loadFrameScript(mm);
+
     // Add stylesheet
     let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
     this.stylesheet = this.chromeWin.document.createProcessingInstruction(
       'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
-    this.chromeWin.document.insertBefore(this.stylesheet, this.chromeWin.document.firstChild);
-
-    this.addPresenter(new VisualPresenter());
+    this.chromeWin.document.insertBefore(this.stylesheet,
+                                         this.chromeWin.document.firstChild);
 
-    // Implicitly add the Android presenter on Android.
-    if (Utils.MozBuildApp == 'mobile/android') {
-      this._androidPresenter = new AndroidPresenter();
-      this.addPresenter(this._androidPresenter);
-    } else if (Utils.MozBuildApp == 'b2g') {
-      this.addPresenter(new SpeechPresenter());
-    }
+    Input.attach(this.chromeWin);
+    Output.attach(this.chromeWin);
+    this.touchAdapter.attach(this.chromeWin);
 
-    VirtualCursorController.attach(this.chromeWin);
-
-    Services.obs.addObserver(this, 'accessible-event', false);
-    this.chromeWin.addEventListener('DOMActivate', this, true);
-    this.chromeWin.addEventListener('resize', this, true);
-    this.chromeWin.addEventListener('scroll', this, true);
-    this.chromeWin.addEventListener('TabOpen', this, true);
-    this.chromeWin.addEventListener('focus', this, true);
+    Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
+    Services.obs.addObserver(this, 'Accessibility:NextObject', false);
+    Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
+    Services.obs.addObserver(this, 'Accessibility:CurrentObject', false);
   },
 
   /**
    * Disable AccessFu and return to default interaction mode.
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
+
     this._enabled = false;
 
     Logger.info('disable');
 
     this.chromeWin.document.removeChild(this.stylesheet);
+    for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
+      mm.sendAsyncMessage('AccessFu:Stop');
 
-    this.presenters.forEach(function(p) { p.detach(); });
-    this.presenters = [];
-
-    VirtualCursorController.detach();
+    Input.detach();
 
-    Services.obs.removeObserver(this, 'accessible-event');
-    this.chromeWin.removeEventListener('DOMActivate', this, true);
-    this.chromeWin.removeEventListener('resize', this, true);
-    this.chromeWin.removeEventListener('scroll', this, true);
-    this.chromeWin.removeEventListener('TabOpen', this, true);
-    this.chromeWin.removeEventListener('focus', this, true);
+    Services.obs.removeObserver(this, 'remote-browser-frame-shown');
+    Services.obs.removeObserver(this, 'Accessibility:NextObject');
+    Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
+    Services.obs.removeObserver(this, 'Accessibility:CurrentObject');
   },
 
-  _processPreferences: function _processPreferences(aEnabled, aTouchEnabled) {
-    let accessPref = ACCESSFU_DISABLE;
+  _enableOrDisable: function _enableOrDisable() {
     try {
-      accessPref = (aEnabled == undefined) ?
-        this.prefsBranch.getIntPref('activate') : aEnabled;
+      if (this._activatePref == ACCESSFU_ENABLE ||
+          this._systemPref && this._activatePref == ACCESSFU_AUTO)
+        this._enable();
+      else
+        this._disable();
     } catch (x) {
-    }
-
-    let ebtPref = ACCESSFU_DISABLE;
-    try {
-      ebtPref = (aTouchEnabled == undefined) ?
-        this.prefsBranch.getIntPref('explorebytouch') : aTouchEnabled;
-    } catch (x) {
+      Logger.error(x);
     }
-
-    if (Utils.MozBuildApp == 'mobile/android') {
-      if (accessPref == ACCESSFU_AUTO) {
-        Cc['@mozilla.org/android/bridge;1'].
-          getService(Ci.nsIAndroidBridge).handleGeckoMessage(
-            JSON.stringify({ gecko: { type: 'Accessibility:Ready' } }));
-        return;
-      }
-    }
-
-    if (accessPref == ACCESSFU_ENABLE)
-      this._enable();
-    else
-      this._disable();
-
-    if (ebtPref == ACCESSFU_ENABLE)
-      this.touchAdapter.attach(this.chromeWin);
-    else
-      this.touchAdapter.detach(this.chromeWin);
-  },
-
-  addPresenter: function addPresenter(presenter) {
-    this.presenters.push(presenter);
-    presenter.attach(this.chromeWin);
   },
 
-  handleEvent: function handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case 'focus':
-      {
-        if (aEvent.target instanceof Ci.nsIDOMWindow) {
-          let docAcc = getAccessible(aEvent.target.document);
-          let docContext = new PresenterContext(docAcc, null);
-          let cursorable = docAcc.QueryInterface(Ci.nsIAccessibleCursorable);
-          let vcContext = new PresenterContext(
-            (cursorable) ? cursorable.virtualCursor.position : null, null);
-          this.presenters.forEach(
-            function(p) { p.tabSelected(docContext, vcContext); });
+  receiveMessage: function receiveMessage(aMessage) {
+    if (Logger.logLevel >= Logger.DEBUG)
+      Logger.debug('Recieved', aMessage.name, JSON.stringify(aMessage.json));
+
+    switch (aMessage.name) {
+      case 'AccessFu:Ready':
+      let mm = Utils.getMessageManager(aMessage.target);
+      mm.sendAsyncMessage('AccessFu:Start',
+                          {method: 'start', buildApp: Utils.MozBuildApp});
+      break;
+      case 'AccessFu:Present':
+      try {
+        for each (let presenter in aMessage.json) {
+          Output[presenter.type](presenter.details, aMessage.target);
+        }
+      } catch (x) {
+        Logger.error(x);
+      }
+      break;
+      case 'AccessFu:Input':
+      Input.setEditState(aMessage.json);
+      break;
+    }
+  },
+
+  _loadFrameScript: function _loadFrameScript(aMessageManager) {
+    aMessageManager.addMessageListener('AccessFu:Present', this);
+    aMessageManager.addMessageListener('AccessFu:Input', this);
+    aMessageManager.addMessageListener('AccessFu:Ready', this);
+    aMessageManager.
+      loadFrameScript(
+        'chrome://global/content/accessibility/content-script.js', true);
+  },
+
+  observe: function observe(aSubject, aTopic, aData) {
+    Logger.debug('observe', aTopic);
+    switch (aTopic) {
+      case 'Accessibility:Settings':
+        this._systemPref = JSON.parse(aData).enabled;
+        this._enableOrDisable();
+        break;
+      case 'Accessibility:NextObject':
+        Input.moveCursor('moveNext', 'Simple', 'gesture');
+        break;
+      case 'Accessibility:PreviousObject':
+        Input.moveCursor('movePrevious', 'Simple', 'gesture');
+        break;
+      case 'Accessibility:CurrentObject':
+        let mm = Utils.getCurrentBrowser(this.chromeWin).
+          frameLoader.messageManager;
+        mm.sendAsyncMessage('AccessFu:VirtualCursor',
+                            {action: 'presentLastPivot'});
+        break;
+      case 'nsPref:changed':
+        if (aData == 'activate') {
+          this._activatePref = this.prefsBranch.getIntPref('activate');
+          this._enableOrDisable();
         }
         break;
-      }
-      case 'TabOpen':
-      {
-        let browser = aEvent.target.linkedBrowser || aEvent.target;
-        // Store the new browser node. We will need to check later when a new
-        // content document is attached if it has been attached to this new tab.
-        // If it has, than we will need to send a 'loading' message along with
-        // the usual 'newdoc' to presenters.
-        this._pendingDocuments[browser] = true;
-        this.presenters.forEach(
-          function(p) {
-            p.tabStateChanged(null, 'newtab');
-          }
-        );
-        break;
-      }
-      case 'DOMActivate':
+      case 'remote-browser-frame-shown':
       {
-        let activatedAcc = getAccessible(aEvent.originalTarget);
-        let state = {};
-        activatedAcc.getState(state, {});
-
-        // Checkable objects will have a state changed event that we will use
-        // instead of this hackish DOMActivate. We will also know the true
-        // action that was taken.
-        if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE)
-          return;
-
-        this.presenters.forEach(function(p) {
-                                  p.actionInvoked(activatedAcc, 'click');
-                                });
-        break;
-      }
-      case 'scroll':
-      case 'resize':
-      {
-        this.presenters.forEach(function(p) { p.viewportChanged(); });
-        break;
-      }
-      case 'mozContentEvent':
-      {
-        if (aEvent.detail.type == 'accessibility-screenreader') {
-          let pref = aEvent.detail.enabled + 0;
-          this._processPreferences(pref, pref);
-        }
+        this._loadFrameScript(
+          aSubject.QueryInterface(Ci.nsIFrameLoader).messageManager);
         break;
       }
     }
   },
 
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case 'Accessibility:Settings':
-        this._processPreferences(JSON.parse(aData).enabled + 0,
-                                 JSON.parse(aData).exploreByTouch + 0);
-        break;
-      case 'Accessibility:NextObject':
-        VirtualCursorController.
-          moveForward(Utils.getCurrentContentDoc(this.chromeWin));
-        break;
-      case 'Accessibility:PreviousObject':
-        VirtualCursorController.
-          moveBackward(Utils.getCurrentContentDoc(this.chromeWin));
-        break;
-      case 'Accessibility:CurrentObject':
-        this._androidPresenter.accessibilityFocus();
-        break;
-      case 'nsPref:changed':
-        this._processPreferences(this.prefsBranch.getIntPref('activate'),
-                                 this.prefsBranch.getIntPref('explorebytouch'));
-        break;
-      case 'accessible-event':
-        let event;
-        try {
-          event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
-          this._handleAccEvent(event);
-        } catch (ex) {
-          Logger.error(ex);
-          return;
-        }
+  handleEvent: function handleEvent(aEvent) {
+    if (aEvent.type == 'mozContentEvent' &&
+        aEvent.detail.type == 'accessibility-screenreader') {
+      this._systemPref = aEvent.detail.enabled;
+      this._enableOrDisable();
     }
   },
 
-  _handleAccEvent: function _handleAccEvent(aEvent) {
-    if (Logger.logLevel <= Logger.DEBUG)
-      Logger.debug(Logger.eventToString(aEvent),
-                   Logger.accessibleToString(aEvent.accessible));
-
-    switch (aEvent.eventType) {
-      case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
-        {
-          let pivot = aEvent.accessible.
-            QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
-          let event = aEvent.
-            QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
-          let position = pivot.position;
-          let doc = aEvent.DOMNode;
-
-          let presenterContext =
-            new PresenterContext(position, event.oldAccessible);
-          let reason = event.reason;
-          this.presenters.forEach(
-            function(p) { p.pivotChanged(presenterContext, reason); });
-
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
-        {
-          let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
-          if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
-              !(event.isExtraState())) {
-            this.presenters.forEach(
-              function(p) {
-                p.actionInvoked(aEvent.accessible,
-                                event.isEnabled() ? 'check' : 'uncheck');
-              }
-            );
-          }
-          else if (event.state == Ci.nsIAccessibleStates.STATE_BUSY &&
-                   !(event.isExtraState()) && event.isEnabled()) {
-            let role = event.accessible.role;
-            if ((role == Ci.nsIAccessibleRole.ROLE_DOCUMENT ||
-                 role == Ci.nsIAccessibleRole.ROLE_APPLICATION)) {
-              // An existing document has changed to state "busy", this means
-              // something is loading. Send a 'loading' message to presenters.
-              this.presenters.forEach(
-                function(p) {
-                  p.tabStateChanged(event.accessible, 'loading');
-                }
-              );
-            }
-          }
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_REORDER:
-        {
-          let acc = aEvent.accessible;
-          if (acc.childCount) {
-            let docAcc = acc.getChildAt(0);
-            if (this._pendingDocuments[aEvent.DOMNode]) {
-              // This is a document in a new tab. Check if it is
-              // in a BUSY state (i.e. loading), and inform presenters.
-              // We need to do this because a state change event will not be
-              // fired when an object is created with the BUSY state.
-              // If this is not a new tab, don't bother because we sent
-              // 'loading' when the previous doc changed its state to BUSY.
-              let state = {};
-              docAcc.getState(state, {});
-              if (state.value & Ci.nsIAccessibleStates.STATE_BUSY &&
-                  this._isNotChromeDoc(docAcc))
-                this.presenters.forEach(
-                  function(p) { p.tabStateChanged(docAcc, 'loading'); }
-                );
-              delete this._pendingDocuments[aEvent.DOMNode];
-            }
-            if (this._isBrowserDoc(docAcc))
-              // A new top-level content document has been attached
-              this.presenters.forEach(
-                function(p) { p.tabStateChanged(docAcc, 'newdoc'); }
-              );
-          }
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE:
-        {
-          if (this._isNotChromeDoc(aEvent.accessible)) {
-            this.presenters.forEach(
-              function(p) {
-                p.tabStateChanged(aEvent.accessible, 'loaded');
-              }
-            );
-          }
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPPED:
-        {
-          this.presenters.forEach(
-            function(p) {
-              p.tabStateChanged(aEvent.accessible, 'loadstopped');
-            }
-          );
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD:
-        {
-          this.presenters.forEach(
-            function(p) {
-              p.tabStateChanged(aEvent.accessible, 'reload');
-            }
-          );
-          break;
-        }
-      case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED:
-      case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED:
-      {
-        if (aEvent.isFromUserInput) {
-          // XXX support live regions as well.
-          let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
-          let isInserted = event.isInserted();
-          let txtIface = aEvent.accessible.QueryInterface(Ci.nsIAccessibleText);
-
-          let text = '';
-          try {
-            text = txtIface.
-              getText(0, Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
-          } catch (x) {
-            // XXX we might have gotten an exception with of a
-            // zero-length text. If we did, ignore it (bug #749810).
-            if (txtIface.characterCount)
-              throw x;
-          }
-
-          this.presenters.forEach(
-            function(p) {
-              p.textChanged(isInserted, event.start, event.length,
-                            text, event.modifiedText);
-            }
-          );
-        }
-        break;
-      }
-      case Ci.nsIAccessibleEvent.EVENT_SCROLLING_START:
-      {
-        VirtualCursorController.moveCursorToObject(
-          Utils.getVirtualCursor(aEvent.accessibleDocument), aEvent.accessible);
-        break;
-      }
-      case Ci.nsIAccessibleEvent.EVENT_FOCUS:
-      {
-        let acc = aEvent.accessible;
-        let doc = aEvent.accessibleDocument;
-        if (acc.role != Ci.nsIAccessibleRole.ROLE_DOCUMENT &&
-            doc.role != Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW)
-          VirtualCursorController.moveCursorToObject(
-            Utils.getVirtualCursor(doc), acc);
-
-        let [,extState] = Utils.getStates(acc);
-        let editableState = extState &
-          (Ci.nsIAccessibleStates.EXT_STATE_EDITABLE |
-           Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE);
-
-        if (editableState != VirtualCursorController.editableState) {
-          if (!VirtualCursorController.editableState)
-            this.presenters.forEach(
-              function(p) {
-                p.editingModeChanged(true);
-              }
-            );
-        }
-        VirtualCursorController.editableState = editableState;
-        break;
-      }
-      default:
-        break;
-    }
-  },
-
-  /**
-   * Check if accessible is a top-level content document (i.e. a child of a XUL
-   * browser node).
-   * @param {nsIAccessible} aDocAcc the accessible to check.
-   * @return {boolean} true if this is a top-level content document.
-   */
-  _isBrowserDoc: function _isBrowserDoc(aDocAcc) {
-    let parent = aDocAcc.parent;
-    if (!parent)
-      return false;
-
-    let domNode = parent.DOMNode;
-    if (!domNode)
-      return false;
-
-    const ns = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-    return (domNode.localName == 'browser' && domNode.namespaceURI == ns);
-  },
-
-  /**
-   * Check if document is not a local "chrome" document, like about:home.
-   * @param {nsIDOMDocument} aDocument the document to check.
-   * @return {boolean} true if this is not a chrome document.
-   */
-  _isNotChromeDoc: function _isNotChromeDoc(aDocument) {
-    let location = aDocument.DOMNode.location;
-    if (!location)
-      return false;
-
-    return location.protocol != 'about:';
-  },
-
-  // A hash of documents that don't yet have an accessible tree.
-  _pendingDocuments: {},
-
   // So we don't enable/disable twice
   _enabled: false
 };
 
-function getAccessible(aNode) {
-  try {
-    return Cc['@mozilla.org/accessibleRetrieval;1'].
-      getService(Ci.nsIAccessibleRetrieval).getAccessibleFor(aNode);
-  } catch (e) {
-    return null;
+var Output = {
+  attach: function attach(aWindow) {
+    this.chromeWin = aWindow;
+  },
+
+  Speech: function Speech(aDetails, aBrowser) {
+    for each (let action in aDetails.actions)
+      Logger.info('tts.' + action.method, '"' + action.data + '"', JSON.stringify(action.options));
+  },
+
+  Visual: function Visual(aDetails, aBrowser) {
+    if (!this.highlightBox) {
+      // Add highlight box
+      this.highlightBox = this.chromeWin.document.
+        createElementNS('http://www.w3.org/1999/xhtml', 'div');
+      this.chromeWin.document.documentElement.appendChild(this.highlightBox);
+      this.highlightBox.id = 'virtual-cursor-box';
+
+      // Add highlight inset for inner shadow
+      let inset = this.chromeWin.document.
+        createElementNS('http://www.w3.org/1999/xhtml', 'div');
+      inset.id = 'virtual-cursor-inset';
+
+      this.highlightBox.appendChild(inset);
+    }
+
+    if (aDetails.method == 'show') {
+      let padding = aDetails.padding;
+      let r = this._adjustBounds(aDetails.bounds, aBrowser);
+
+      // First hide it to avoid flickering when changing the style.
+      this.highlightBox.style.display = 'none';
+      this.highlightBox.style.top = (r.top - padding) + 'px';
+      this.highlightBox.style.left = (r.left - padding) + 'px';
+      this.highlightBox.style.width = (r.width + padding*2) + 'px';
+      this.highlightBox.style.height = (r.height + padding*2) + 'px';
+      this.highlightBox.style.display = 'block';
+    } else if (aDetails.method == 'hide') {
+      this.highlightBox.style.display = 'none';
+    }
+  },
+
+  Android: function Android(aDetails, aBrowser) {
+    if (!this._bridge)
+      this._bridge = Cc['@mozilla.org/android/bridge;1'].getService(Ci.nsIAndroidBridge);
+
+    for each (let androidEvent in aDetails) {
+      androidEvent.type = 'Accessibility:Event';
+      if (androidEvent.bounds)
+        androidEvent.bounds = this._adjustBounds(androidEvent.bounds, aBrowser);
+      this._bridge.handleGeckoMessage(JSON.stringify({gecko: androidEvent}));
+    }
+  },
+
+  _adjustBounds: function(aJsonBounds, aBrowser) {
+    let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
+                          aJsonBounds.right - aJsonBounds.left,
+                          aJsonBounds.bottom - aJsonBounds.top);
+    let vp = Utils.getViewport(this.chromeWin) || { zoom: 1.0, offsetY: 0 };
+    let browserOffset = aBrowser.getBoundingClientRect();
+
+    return bounds.translate(browserOffset.left, browserOffset.top).
+      scale(vp.zoom, vp.zoom).expandToIntegers();
   }
-}
+};
+
+var Input = {
+  editState: {},
+
+  attach: function attach(aWindow) {
+    this.chromeWin = aWindow;
+    this.chromeWin.document.addEventListener('keypress', this, true);
+    this.chromeWin.addEventListener('mozAccessFuGesture', this, true);
+  },
+
+  detach: function detach() {
+    this.chromeWin.document.removeEventListener('keypress', this, true);
+    this.chromeWin.removeEventListener('mozAccessFuGesture', this, true);
+  },
+
+  handleEvent: function Input_handleEvent(aEvent) {
+    try {
+      switch (aEvent.type) {
+      case 'keypress':
+        this._handleKeypress(aEvent);
+        break;
+      case 'mozAccessFuGesture':
+        this._handleGesture(aEvent);
+        break;
+      }
+    } catch (x) {
+      Logger.error(x);
+    }
+  },
+
+  _handleGesture: function _handleGesture(aEvent) {
+    let detail = aEvent.detail;
+    Logger.info('Gesture', detail.type,
+                '(fingers: ' + detail.touches.length + ')');
+
+    if (detail.touches.length == 1) {
+      switch (detail.type) {
+        case 'swiperight':
+          this.moveCursor('moveNext', 'Simple', 'gestures');
+          break;
+        case 'swipeleft':
+          this.moveCursor('movePrevious', 'Simple', 'gesture');
+          break;
+        case 'doubletap':
+          this.activateCurrent();
+          break;
+        case 'explore':
+          this.moveCursor('moveToPoint', 'Simple', 'gesture',
+                          detail.x, detail.y);
+          break;
+      }
+    }
+
+    if (detail.touches.length == 3) {
+      switch (detail.type) {
+        case 'swiperight':
+          this.scroll(-1, true);
+          break;
+        case 'swipedown':
+          this.scroll(-1);
+          break;
+        case 'swipeleft':
+          this.scroll(1, true);
+          break;
+        case 'swipeup':
+          this.scroll(1);
+          break;
+      }
+    }
+  },
+
+  _handleKeypress: function _handleKeypress(aEvent) {
+    let target = aEvent.target;
+
+    // Ignore keys with modifiers so the content could take advantage of them.
+    if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
+      return;
+
+    switch (aEvent.keyCode) {
+      case 0:
+        // an alphanumeric key was pressed, handle it separately.
+        // If it was pressed with either alt or ctrl, just pass through.
+        // If it was pressed with meta, pass the key on without the meta.
+        if (this.editState.editing)
+          return;
+
+        let key = String.fromCharCode(aEvent.charCode);
+        try {
+          let [methodName, rule] = this.keyMap[key];
+          this.moveCursor(methodName, rule, 'keyboard');
+        } catch (x) {
+          return;
+        }
+        break;
+      case aEvent.DOM_VK_RIGHT:
+        if (this.editState.editing) {
+          if (!this.editState.atEnd)
+            // Don't move forward if caret is not at end of entry.
+            // XXX: Fix for rtl
+            return;
+          else
+            target.blur();
+        }
+        this.moveCursor(aEvent.shiftKey ? 'moveLast' : 'moveNext', 'Simple', 'keyboard');
+        break;
+      case aEvent.DOM_VK_LEFT:
+        if (this.editState.editing) {
+          if (!this.editState.atStart)
+            // Don't move backward if caret is not at start of entry.
+            // XXX: Fix for rtl
+            return;
+          else
+            target.blur();
+        }
+        this.moveCursor(aEvent.shiftKey ? 'moveFirst' : 'movePrevious', 'Simple', 'keyboard');
+        break;
+      case aEvent.DOM_VK_UP:
+        if (this.editState.multiline) {
+          if (!this.editState.atStart)
+            // Don't blur content if caret is not at start of text area.
+            return;
+          else
+            target.blur();
+        }
+
+        if (Utils.MozBuildApp == 'mobile/android')
+          // Return focus to native Android browser chrome.
+          Cc['@mozilla.org/android/bridge;1'].
+            getService(Ci.nsIAndroidBridge).handleGeckoMessage(
+              JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
+        break;
+      case aEvent.DOM_VK_RETURN:
+      case aEvent.DOM_VK_ENTER:
+        if (this.editState.editing)
+          return;
+        this.activateCurrent();
+        break;
+    default:
+      return;
+    }
+
+    aEvent.preventDefault();
+    aEvent.stopPropagation();
+  },
+
+  moveCursor: function moveCursor(aAction, aRule, aInputType, aX, aY) {
+    let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+    mm.sendAsyncMessage('AccessFu:VirtualCursor',
+                        {action: aAction, rule: aRule,
+                         x: aX, y: aY, origin: 'top',
+                         inputType: aInputType});
+  },
+
+  activateCurrent: function activateCurrent() {
+    let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+    mm.sendAsyncMessage('AccessFu:Activate', {});
+  },
+
+  setEditState: function setEditState(aEditState) {
+    this.editState = aEditState;
+  },
+
+  scroll: function scroll(aPage, aHorizontal) {
+    let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+    mm.sendAsyncMessage('AccessFu:Scroll', {page: aPage, horizontal: aHorizontal, origin: 'top'});
+  },
+
+  keyMap: {
+    a: ['moveNext', 'Anchor'],
+    A: ['movePrevious', 'Anchor'],
+    b: ['moveNext', 'Button'],
+    B: ['movePrevious', 'Button'],
+    c: ['moveNext', 'Combobox'],
+    C: ['movePrevious', 'Combobox'],
+    e: ['moveNext', 'Entry'],
+    E: ['movePrevious', 'Entry'],
+    f: ['moveNext', 'FormElement'],
+    F: ['movePrevious', 'FormElement'],
+    g: ['moveNext', 'Graphic'],
+    G: ['movePrevious', 'Graphic'],
+    h: ['moveNext', 'Heading'],
+    H: ['movePrevious', 'Heading'],
+    i: ['moveNext', 'ListItem'],
+    I: ['movePrevious', 'ListItem'],
+    k: ['moveNext', 'Link'],
+    K: ['movePrevious', 'Link'],
+    l: ['moveNext', 'List'],
+    L: ['movePrevious', 'List'],
+    p: ['moveNext', 'PageTab'],
+    P: ['movePrevious', 'PageTab'],
+    r: ['moveNext', 'RadioButton'],
+    R: ['movePrevious', 'RadioButton'],
+    s: ['moveNext', 'Separator'],
+    S: ['movePrevious', 'Separator'],
+    t: ['moveNext', 'Table'],
+    T: ['movePrevious', 'Table'],
+    x: ['moveNext', 'Checkbox'],
+    X: ['movePrevious', 'Checkbox']
+  }
+};
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/EventManager.jsm
@@ -0,0 +1,299 @@
+/* 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/. */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+var Cr = Components.results;
+
+Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
+Cu.import('resource://gre/modules/accessibility/TraversalRules.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+var EXPORTED_SYMBOLS = ['EventManager'];
+
+var EventManager = {
+  editState: {},
+
+  start: function start(aSendMsgFunc) {
+    try {
+      if (!this._started) {
+        this.sendMsgFunc = aSendMsgFunc || function() {};
+        this.presenters = [new VisualPresenter()];
+
+        if (Utils.MozBuildApp == 'b2g') {
+          this.presenters.push(new SpeechPresenter());
+        } else if (Utils.MozBuildApp == 'mobile/android') {
+          this.presenters.push(new AndroidPresenter());
+        }
+
+        Logger.info('EventManager.start', Utils.MozBuildApp, [p.type for each(p in this.presenters)].join(', '));
+
+        this._started = true;
+        Services.obs.addObserver(this, 'accessible-event', false);
+      }
+
+      this.present(
+        function(p) {
+          return p.tabStateChanged(null, 'newtab');
+        }
+      );
+    } catch (x) {
+      Logger.error('Failed to start EventManager:', x);
+    }
+  },
+
+  stop: function stop() {
+    Services.obs.removeObserver(this, 'accessible-event');
+    this.presenters = [];
+    this._started = false;
+  },
+
+  handleEvent: function handleEvent(aEvent) {
+    try {
+      switch (aEvent.type) {
+      case 'DOMActivate':
+      {
+        let activatedAcc =
+          Utils.AccRetrieval.getAccessibleFor(aEvent.originalTarget);
+        let [state, extState] = Utils.getStates(activatedAcc);
+
+        // Checkable objects will have a state changed event that we will use
+        // instead of this hackish DOMActivate. We will also know the true
+        // action that was taken.
+        if (state & Ci.nsIAccessibleStates.STATE_CHECKABLE)
+          return;
+
+        this.present(
+          function(p) {
+            return p.actionInvoked(activatedAcc, 'click');
+          }
+        );
+        break;
+      }
+      case 'scroll':
+      case 'resize':
+      {
+        this.present(
+          function(p) {
+            return p.viewportChanged();;
+          }
+        );
+        break;
+      }
+      }
+    } catch (x) {
+      Logger.error('Error handling DOM event:', x);
+    }
+  },
+
+  observe: function observe(aSubject, aTopic, aData) {
+    switch (aTopic) {
+      case 'accessible-event':
+        var event;
+        try {
+          event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
+          this.handleAccEvent(event);
+        } catch (x) {
+          Logger.error('Error handing accessible event:', x);
+          return;
+        }
+    }
+  },
+
+  presentLastPivot: function presentLastPivot() {
+    this.present(
+      function(p) {
+        return p.presentLastPivot();
+      }
+    );
+  },
+
+  handleAccEvent: function handleAccEvent(aEvent) {
+    if (Logger.logLevel >= Logger.DEBUG)
+      Logger.debug('A11yEvent', Logger.eventToString(aEvent),
+                   Logger.accessibleToString(aEvent.accessible));
+
+    switch (aEvent.eventType) {
+      case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
+      {
+        let pivot = aEvent.accessible.
+          QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
+        let position = pivot.position;
+        if (position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
+          break;
+        let event = aEvent.
+          QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
+        let presenterContext =
+          new PresenterContext(position, event.oldAccessible);
+        let reason = event.reason;
+
+        if (this.editState.editing)
+          aEvent.accessibleDocument.takeFocus();
+
+        this.present(
+          function(p) {
+            return p.pivotChanged(presenterContext, reason);
+          }
+        );
+        break;
+      }
+      case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
+      {
+        let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
+        if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
+            !(event.isExtraState())) {
+          this.present(
+            function(p) {
+              return p.actionInvoked(aEvent.accessible,
+                                     event.isEnabled() ? 'check' : 'uncheck');
+            }
+          );
+        }
+        break;
+      }
+      case Ci.nsIAccessibleEvent.EVENT_SCROLLING_START:
+      {
+        let vc = Utils.getVirtualCursor(aEvent.accessibleDocument);
+        vc.moveNext(TraversalRules.Simple, aEvent.accessible, true);
+        break;
+      }
+      case Ci.nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED:
+      {
+        let acc = aEvent.accessible;
+        let characterCount = acc.
+          QueryInterface(Ci.nsIAccessibleText).characterCount;
+        let caretOffset = aEvent.
+          QueryInterface(Ci.nsIAccessibleCaretMoveEvent).caretOffset;
+
+        // Update editing state, both for presenter and other things
+        let [,extState] = Utils.getStates(acc);
+        let editState = {
+          editing: !!(extState & Ci.nsIAccessibleStates.EXT_STATE_EDITABLE),
+          multiline: !!(extState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE),
+          atStart: caretOffset == 0,
+          atEnd: caretOffset == characterCount
+        };
+
+        // Not interesting
+        if (!editState.editing && editState.editing == this.editState.editing)
+          break;
+
+        if (editState.editing != this.editState.editing)
+          this.present(
+            function(p) {
+              return p.editingModeChanged(editState.editing);
+            }
+          );
+
+        if (editState.editing != this.editState.editing ||
+            editState.multiline != this.editState.multiline ||
+            editState.atEnd != this.editState.atEnd ||
+            editState.atStart != this.editState.atStart)
+          this.sendMsgFunc("AccessFu:Input", editState);
+
+        this.editState = editState;
+        break;
+      }
+      case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED:
+      case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED:
+      {
+        if (aEvent.isFromUserInput) {
+          // XXX support live regions as well.
+          let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
+          let isInserted = event.isInserted();
+          let txtIface = aEvent.accessible.QueryInterface(Ci.nsIAccessibleText);
+
+          let text = '';
+          try {
+            text = txtIface.
+              getText(0, Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
+          } catch (x) {
+            // XXX we might have gotten an exception with of a
+            // zero-length text. If we did, ignore it (bug #749810).
+            if (txtIface.characterCount)
+              throw x;
+          }
+          this.present(
+            function(p) {
+              return p.textChanged(isInserted, event.start, event.length,
+                                   text, event.modifiedText);
+            }
+          );
+        }
+        break;
+      }
+      case Ci.nsIAccessibleEvent.EVENT_FOCUS:
+      {
+        // Put vc where the focus is at
+        let acc = aEvent.accessible;
+        let doc = aEvent.accessibleDocument;
+        if (acc.role != Ci.nsIAccessibleRole.ROLE_DOCUMENT &&
+            doc.role != Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW) {
+          let vc = Utils.getVirtualCursor(doc);
+          vc.moveNext(TraversalRules.Simple, acc, true);
+        }
+        break;
+      }
+    }
+  },
+
+  present: function present(aPresenterFunc) {
+    try {
+      this.sendMsgFunc(
+        "AccessFu:Present",
+        [aPresenterFunc(p) for each (p in this.presenters)].
+          filter(function(d) {return !!d;}));
+    } catch (x) {
+      Logger.error(x);
+    }
+  },
+
+  onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
+    let tabstate = '';
+
+    let loadingState = Ci.nsIWebProgressListener.STATE_TRANSFERRING |
+      Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+    let loadedState = Ci.nsIWebProgressListener.STATE_STOP |
+      Ci.nsIWebProgressListener.STATE_IS_NETWORK;
+
+    if ((aStateFlags & loadingState) == loadingState) {
+      tabstate = 'loading';
+    } else if ((aStateFlags & loadedState) == loadedState &&
+               !aWebProgress.isLoadingDocument) {
+      tabstate = 'loaded';
+    }
+
+    if (tabstate) {
+      let docAcc = Utils.AccRetrieval.getAccessibleFor(aWebProgress.DOMWindow.document);
+      this.present(
+        function(p) {
+          return p.tabStateChanged(docAcc, tabstate);
+        }
+      );
+    }
+  },
+
+  onProgressChange: function onProgressChange() {},
+
+  onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
+    let docAcc = Utils.AccRetrieval.getAccessibleFor(aWebProgress.DOMWindow.document);
+    this.present(
+      function(p) {
+        return p.tabStateChanged(docAcc, 'newdoc');
+      }
+    );
+  },
+
+  onStatusChange: function onStatusChange() {},
+
+  onSecurityChange: function onSecurityChange() {},
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                         Ci.nsISupportsWeakReference,
+                                         Ci.nsISupports,
+                                         Ci.nsIObserver])
+};
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -22,16 +22,21 @@ var EXPORTED_SYMBOLS = ['VisualPresenter
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
 
 Presenter.prototype = {
   /**
+   * The type of presenter. Used for matching it with the appropriate output method.
+   */
+  type: 'Base',
+
+  /**
    * Attach function for presenter.
    * @param {ChromeWindow} aWindow Chrome window the presenter could use.
    */
   attach: function attach(aWindow) {},
 
   /**
    * Detach function.
    */
@@ -87,318 +92,141 @@ Presenter.prototype = {
    * @param {PresenterContext} aVCContext context object for tab's current
    *   virtual cursor position.
    */
   tabSelected: function tabSelected(aDocContext, aVCContext) {},
 
   /**
    * The viewport has changed, either a scroll, pan, zoom, or
    *    landscape/portrait toggle.
+   * @param {Window} aWindow window of viewport that changed.
    */
-  viewportChanged: function viewportChanged() {},
+  viewportChanged: function viewportChanged(aWindow) {},
 
   /**
    * We have entered or left text editing mode.
    */
-  editingModeChanged: function editingModeChanged(aIsEditing) {}
+  editingModeChanged: function editingModeChanged(aIsEditing) {},
+
+  /**
+   * Re-present the last pivot change.
+   */
+  presentLastPivot: function AndroidPresenter_presentLastPivot() {}
 };
 
 /**
  * Visual presenter. Draws a box around the virtual cursor's position.
  */
 
 function VisualPresenter() {}
 
 VisualPresenter.prototype = {
   __proto__: Presenter.prototype,
 
+  type: 'Visual',
+
   /**
    * The padding in pixels between the object and the highlight border.
    */
   BORDER_PADDING: 2,
 
-  attach: function VisualPresenter_attach(aWindow) {
-    this.chromeWin = aWindow;
-
-    // Add highlight box
-    this.highlightBox = this.chromeWin.document.
-      createElementNS('http://www.w3.org/1999/xhtml', 'div');
-    this.chromeWin.document.documentElement.appendChild(this.highlightBox);
-    this.highlightBox.id = 'virtual-cursor-box';
+  viewportChanged: function VisualPresenter_viewportChanged(aWindow) {
+    if (this._currentContext)
+      return {
+        type: this.type,
+        details: {
+          method: 'show',
+          bounds: this._currentContext.bounds,
+          padding: this.BORDER_PADDING
+        }
+      };
 
-    // Add highlight inset for inner shadow
-    let inset = this.chromeWin.document.
-      createElementNS('http://www.w3.org/1999/xhtml', 'div');
-    inset.id = 'virtual-cursor-inset';
-
-    this.highlightBox.appendChild(inset);
-  },
-
-  detach: function VisualPresenter_detach() {
-    this.highlightBox.parentNode.removeChild(this.highlightBox);
-    this.highlightBox = this.stylesheet = null;
-  },
-
-  viewportChanged: function VisualPresenter_viewportChanged() {
-    if (this._currentContext)
-      this._highlight(this._currentContext);
+    return null;
   },
 
   pivotChanged: function VisualPresenter_pivotChanged(aContext, aReason) {
     this._currentContext = aContext;
 
-    if (!aContext.accessible) {
-      this._hide();
-      return;
-    }
+    if (!aContext.accessible)
+      return {type: this.type, details: {method: 'hide'}};
 
     try {
       aContext.accessible.scrollTo(
         Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
-      this._highlight(aContext);
+      return {
+        type: this.type,
+        details: {
+          method: 'show',
+          bounds: aContext.bounds,
+          padding: this.BORDER_PADDING
+        }
+      };
     } catch (e) {
       Logger.error('Failed to get bounds: ' + e);
-      return;
+      return null;
     }
   },
 
   tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) {
-    this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
+    return this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
   },
 
   tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj,
                                                             aPageState) {
     if (aPageState == 'newdoc')
-      this._hide();
-  },
-
-  // Internals
-
-  _hide: function _hide() {
-    this.highlightBox.style.display = 'none';
-  },
+      return {type: this.type, details: {method: 'hide'}};
 
-  _highlight: function _highlight(aContext) {
-    let vp = Utils.getViewport(this.chromeWin) || { zoom: 1.0, offsetY: 0 };
-    let r = aContext.bounds.scale(vp.zoom, vp.zoom).expandToIntegers();
-
-    // First hide it to avoid flickering when changing the style.
-    this.highlightBox.style.display = 'none';
-    this.highlightBox.style.top = (r.top - this.BORDER_PADDING) + 'px';
-    this.highlightBox.style.left = (r.left - this.BORDER_PADDING) + 'px';
-    this.highlightBox.style.width = (r.width + this.BORDER_PADDING*2) + 'px';
-    this.highlightBox.style.height = (r.height + this.BORDER_PADDING*2) + 'px';
-    this.highlightBox.style.display = 'block';
+    return null;
   }
 };
 
 /**
  * Android presenter. Fires Android a11y events.
  */
 
 function AndroidPresenter() {}
 
 AndroidPresenter.prototype = {
   __proto__: Presenter.prototype,
 
+  type: 'Android',
+
   // Android AccessibilityEvent type constants.
   ANDROID_VIEW_CLICKED: 0x01,
   ANDROID_VIEW_LONG_CLICKED: 0x02,
   ANDROID_VIEW_SELECTED: 0x04,
   ANDROID_VIEW_FOCUSED: 0x08,
   ANDROID_VIEW_TEXT_CHANGED: 0x10,
   ANDROID_WINDOW_STATE_CHANGED: 0x20,
   ANDROID_VIEW_HOVER_ENTER: 0x80,
   ANDROID_VIEW_HOVER_EXIT: 0x100,
   ANDROID_VIEW_SCROLLED: 0x1000,
   ANDROID_ANNOUNCEMENT: 0x4000,
   ANDROID_VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
 
-  attach: function AndroidPresenter_attach(aWindow) {
-    this.chromeWin = aWindow;
-  },
-
   pivotChanged: function AndroidPresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible)
-      return;
+      return null;
 
     this._currentContext = aContext;
 
+    let androidEvents = [];
+
     let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
                             Utils.AndroidSdkVersion >= 14);
     let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
       this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED :
       this.ANDROID_VIEW_FOCUSED;
 
     if (isExploreByTouch) {
       // This isn't really used by TalkBack so this is a half-hearted attempt
       // for now.
-      this.sendMessageToJava({
-         gecko: {
-           type: 'Accessibility:Event',
-           eventType: this.ANDROID_VIEW_HOVER_EXIT,
-           text: []
-         }
-      });
-    }
-
-    let vp = Utils.getViewport(this.chromeWin) || { zoom: 1.0, offsetY: 0 };
-    let bounds = aContext.bounds.scale(vp.zoom, vp.zoom).expandToIntegers();
-    let output = [];
-
-    aContext.newAncestry.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
-    output.push.apply(output,
-                      UtteranceGenerator.genForObject(aContext.accessible));
-
-    aContext.subtreePreorder.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
-    this.sendMessageToJava({
-      gecko: {
-        type: 'Accessibility:Event',
-        eventType: (isExploreByTouch) ? this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
-        text: output,
-        bounds: bounds
-      }
-    });
-  },
-
-  actionInvoked: function AndroidPresenter_actionInvoked(aObject, aActionName) {
-    this.sendMessageToJava({
-      gecko: {
-        type: 'Accessibility:Event',
-        eventType: this.ANDROID_VIEW_CLICKED,
-        text: UtteranceGenerator.genForAction(aObject, aActionName)
-      }
-    });
-  },
-
-  tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) {
-    // Send a pivot change message with the full context utterance for this doc.
-    this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
-  },
-
-  tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
-                                                             aPageState) {
-    this._appAnnounce(
-      UtteranceGenerator.genForTabStateChange(aDocObj, aPageState));
-  },
-
-  textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart,
-                                                     aLength, aText,
-                                                     aModifiedText) {
-    let androidEvent = {
-      type: 'Accessibility:Event',
-      eventType: this.ANDROID_VIEW_TEXT_CHANGED,
-      text: [aText],
-      fromIndex: aStart,
-      removedCount: 0,
-      addedCount: 0
-    };
-
-    if (aIsInserted) {
-      androidEvent.addedCount = aLength;
-      androidEvent.beforeText =
-        aText.substring(0, aStart) + aText.substring(aStart + aLength);
-    } else {
-      androidEvent.removedCount = aLength;
-      androidEvent.beforeText =
-        aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
+      androidEvents.push({eventType: this.ANDROID_VIEW_HOVER_EXIT, text: []});
     }
 
-    this.sendMessageToJava({gecko: androidEvent});
-  },
-
-  viewportChanged: function AndroidPresenter_viewportChanged() {
-    if (Utils.AndroidSdkVersion < 14)
-      return;
-
-    let win = Utils.getBrowserApp(this.chromeWin).selectedBrowser.contentWindow;
-    this.sendMessageToJava({
-      gecko: {
-        type: 'Accessibility:Event',
-        eventType: this.ANDROID_VIEW_SCROLLED,
-        text: [],
-        scrollX: win.scrollX,
-        scrollY: win.scrollY,
-        maxScrollX: win.scrollMaxX,
-        maxScrollY: win.scrollMaxY
-      }
-    });
-  },
-
-  editingModeChanged: function AndroidPresenter_editingModeChanged(aIsEditing) {
-    this._appAnnounce(UtteranceGenerator.genForEditingMode(aIsEditing));
-  },
-
-  _appAnnounce: function _appAnnounce(aUtterance) {
-    if (!aUtterance.length)
-      return;
-
-    this.sendMessageToJava({
-      gecko: {
-        type: 'Accessibility:Event',
-        eventType: (Utils.AndroidSdkVersion >= 16) ?
-          this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
-        text: aUtterance,
-        addedCount: aUtterance.join(' ').length,
-        removedCount: 0,
-        fromIndex: 0
-      }
-    });
-  },
-
-  accessibilityFocus: function AndroidPresenter_accessibilityFocus() {
-    if (this._currentContext)
-      this.pivotChanged(this._currentContext);
-  },
-
-  sendMessageToJava: function AndroidPresenter_sendMessageTojava(aMessage) {
-    return Cc['@mozilla.org/android/bridge;1'].
-      getService(Ci.nsIAndroidBridge).
-      handleGeckoMessage(JSON.stringify(aMessage));
-  }
-};
-
-/**
- * A dummy Android presenter for desktop testing
- */
-
-function DummyAndroidPresenter() {}
-
-DummyAndroidPresenter.prototype = {
-  __proto__: AndroidPresenter.prototype,
-
-  sendMessageToJava: function DummyAndroidPresenter_sendMessageToJava(aMsg) {
-    Logger.debug('Android event:\n' + JSON.stringify(aMsg, null, 2));
-  }
-};
-
-/**
- * A speech presenter for direct TTS output
- */
-
-function SpeechPresenter() {}
-
-SpeechPresenter.prototype = {
-  __proto__: Presenter.prototype,
-
-
-  pivotChanged: function SpeechPresenter_pivotChanged(aContext, aReason) {
-    if (!aContext.accessible)
-      return;
-
     let output = [];
 
     aContext.newAncestry.forEach(
       function(acc) {
         output.push.apply(output, UtteranceGenerator.genForObject(acc));
       }
     );
 
@@ -406,19 +234,163 @@ SpeechPresenter.prototype = {
                       UtteranceGenerator.genForObject(aContext.accessible));
 
     aContext.subtreePreorder.forEach(
       function(acc) {
         output.push.apply(output, UtteranceGenerator.genForObject(acc));
       }
     );
 
-    Logger.info('SPEAK', '"' + output.join(' ') + '"');
+    androidEvents.push({eventType: (isExploreByTouch) ?
+                          this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
+                        text: output,
+                        bounds: aContext.bounds});
+    return {
+      type: this.type,
+      details: androidEvents
+    };
+  },
+
+  actionInvoked: function AndroidPresenter_actionInvoked(aObject, aActionName) {
+    return {
+      type: this.type,
+      details: [{
+        eventType: this.ANDROID_VIEW_CLICKED,
+        text: UtteranceGenerator.genForAction(aObject, aActionName)
+      }]
+    };
+  },
+
+  tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) {
+    // Send a pivot change message with the full context utterance for this doc.
+    return this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
+  },
+
+  tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
+                                                             aPageState) {
+    return this._appAnnounce(
+      UtteranceGenerator.genForTabStateChange(aDocObj, aPageState));
+  },
+
+  textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart,
+                                                     aLength, aText,
+                                                     aModifiedText) {
+    let androidEvent = {
+      type: this.type,
+      details: [{
+        eventType: this.ANDROID_VIEW_TEXT_CHANGED,
+        text: [aText],
+        fromIndex: aStart,
+        removedCount: 0,
+        addedCount: 0
+      }]
+    };
+
+    if (aIsInserted) {
+      androidEvent.addedCount = aLength;
+      androidEvent.beforeText =
+        aText.substring(0, aStart) + aText.substring(aStart + aLength);
+    } else {
+      androidEvent.removedCount = aLength;
+      androidEvent.beforeText =
+        aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
+    }
+
+    return androidEvent;
+  },
+
+  viewportChanged: function AndroidPresenter_viewportChanged(aWindow) {
+    if (Utils.AndroidSdkVersion < 14)
+      return null;
+
+    return {
+      type: this.type,
+      details: [{
+        eventType: this.ANDROID_VIEW_SCROLLED,
+        text: [],
+        scrollX: aWindow.scrollX,
+        scrollY: aWindow.scrollY,
+        maxScrollX: aWindow.scrollMaxX,
+        maxScrollY: aWindow.scrollMaxY
+      }]
+    };
+  },
+
+  editingModeChanged: function AndroidPresenter_editingModeChanged(aIsEditing) {
+    return this._appAnnounce(UtteranceGenerator.genForEditingMode(aIsEditing));
+  },
+
+  _appAnnounce: function _appAnnounce(aUtterance) {
+    if (!aUtterance.length)
+      return null;
+
+    return {
+      type: this.type,
+      details: [{
+        eventType: (Utils.AndroidSdkVersion >= 16) ?
+          this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
+        text: aUtterance,
+        addedCount: aUtterance.join(' ').length,
+        removedCount: 0,
+        fromIndex: 0
+      }]
+    };
+  },
+
+  presentLastPivot: function AndroidPresenter_presentLastPivot() {
+    if (this._currentContext)
+      return this.pivotChanged(this._currentContext);
+    else
+      return null;
   }
-}
+};
+
+/**
+ * A speech presenter for direct TTS output
+ */
+
+function SpeechPresenter() {}
+
+SpeechPresenter.prototype = {
+  __proto__: Presenter.prototype,
+
+  type: 'Speech',
+
+  pivotChanged: function SpeechPresenter_pivotChanged(aContext, aReason) {
+    if (!aContext.accessible)
+      return null;
+
+    let output = [];
+
+    aContext.newAncestry.forEach(
+      function(acc) {
+        output.push.apply(output, UtteranceGenerator.genForObject(acc));
+      }
+    );
+
+    output.push.apply(output,
+                      UtteranceGenerator.genForObject(aContext.accessible));
+
+    aContext.subtreePreorder.forEach(
+      function(acc) {
+        output.push.apply(output, UtteranceGenerator.genForObject(acc));
+      }
+    );
+
+    return {
+      type: this.type,
+      details: {
+        actions: [
+          {method: 'playEarcon', data: 'tick', options: {}},
+          {method: 'speak', data: output.join(' '), options: {enqueue: true}}
+        ]
+      }
+    };
+  }
+};
 
 /**
  * PresenterContext: An object that generates and caches context information
  * for a given accessible and its relationship with another accessible.
  */
 function PresenterContext(aAccessible, aOldAccessible) {
   this._accessible = aAccessible;
   this._oldAccessible =
@@ -499,17 +471,18 @@ PresenterContext.prototype = {
   },
 
   get bounds() {
     if (!this._bounds) {
       let objX = {}, objY = {}, objW = {}, objH = {};
 
       this._accessible.getBounds(objX, objY, objW, objH);
 
-      // Can't specify relative coords in nsIAccessible.getBounds, so we do it.
+      // XXX: OOP content provides a screen offset of 0, while in-process provides a real
+      // offset. Removing the offset and using content-relative coords normalizes this.
       let docX = {}, docY = {};
       let docRoot = this._accessible.rootDocument.
         QueryInterface(Ci.nsIAccessible);
       docRoot.getBounds(docX, docY, {}, {});
 
       this._bounds = new Rect(objX.value, objY.value, objW.value, objH.value).
         translate(-docX.value, -docY.value);
     }
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/TraversalRules.jsm
@@ -0,0 +1,207 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+var EXPORTED_SYMBOLS = ['TraversalRules'];
+
+Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+function BaseTraversalRule(aRoles, aMatchFunc) {
+  this._matchRoles = aRoles;
+  this._matchFunc = aMatchFunc;
+}
+
+BaseTraversalRule.prototype = {
+    getMatchRoles: function BaseTraversalRule_getmatchRoles(aRules) {
+      aRules.value = this._matchRoles;
+      return aRules.value.length;
+    },
+
+    preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
+    Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
+
+    match: function BaseTraversalRule_match(aAccessible)
+    {
+      if (aAccessible.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
+        return (aAccessible.childCount) ?
+          Ci.nsIAccessibleTraversalRule.FILTER_IGNORE :
+          Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      }
+
+      if (this._matchFunc)
+        return this._matchFunc(aAccessible);
+
+      return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
+};
+
+var gSimpleTraversalRoles =
+  [Ci.nsIAccessibleRole.ROLE_MENUITEM,
+   Ci.nsIAccessibleRole.ROLE_LINK,
+   Ci.nsIAccessibleRole.ROLE_PAGETAB,
+   Ci.nsIAccessibleRole.ROLE_GRAPHIC,
+   // XXX: Find a better solution for ROLE_STATICTEXT.
+   // It allows to filter list bullets but at the same time it
+   // filters CSS generated content too as an unwanted side effect.
+   // Ci.nsIAccessibleRole.ROLE_STATICTEXT,
+   Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
+   Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
+   Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
+   Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
+   Ci.nsIAccessibleRole.ROLE_COMBOBOX,
+   Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
+   Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
+   Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
+   Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
+   Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
+   Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
+   Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
+   Ci.nsIAccessibleRole.ROLE_ENTRY,
+   // Used for traversing in to child OOP frames.
+   Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME];
+
+var TraversalRules = {
+  Simple: new BaseTraversalRule(
+    gSimpleTraversalRoles,
+    function Simple_match(aAccessible) {
+      switch (aAccessible.role) {
+      case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
+        // We don't want to ignore the subtree because this is often
+        // where the list box hangs out.
+        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
+        {
+          // Nameless text leaves are boring, skip them.
+          let name = aAccessible.name;
+          if (name && name.trim())
+            return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+          else
+            return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+        }
+      case Ci.nsIAccessibleRole.ROLE_LINK:
+        // If the link has children we should land on them instead.
+        // Image map links don't have children so we need to match those.
+        if (aAccessible.childCount == 0)
+          return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+        else
+          return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+      default:
+        // Ignore the subtree, if there is one. So that we don't land on
+        // the same content that was already presented by its parent.
+        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
+          Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
+      }
+    }
+  ),
+
+  SimpleTouch: new BaseTraversalRule(
+    gSimpleTraversalRoles,
+    function Simple_match(aAccessible) {
+      return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
+        Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
+    }
+  ),
+
+  Anchor: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_LINK],
+    function Anchor_match(aAccessible)
+    {
+      // We want to ignore links, only focus named anchors.
+      let state = {};
+      let extraState = {};
+      aAccessible.getState(state, extraState);
+      if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
+        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+      } else {
+        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      }
+    }),
+
+  Button: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
+     Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
+     Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
+     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
+     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID]),
+
+  Combobox: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_COMBOBOX,
+     Ci.nsIAccessibleRole.ROLE_LISTBOX]),
+
+  Entry: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_ENTRY,
+     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT]),
+
+  FormElement: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
+     Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
+     Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
+     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
+     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID,
+     Ci.nsIAccessibleRole.ROLE_COMBOBOX,
+     Ci.nsIAccessibleRole.ROLE_LISTBOX,
+     Ci.nsIAccessibleRole.ROLE_ENTRY,
+     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
+     Ci.nsIAccessibleRole.ROLE_PAGETAB,
+     Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
+     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
+     Ci.nsIAccessibleRole.ROLE_SLIDER,
+     Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
+     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM]),
+
+  Graphic: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_GRAPHIC]),
+
+  Heading: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_HEADING]),
+
+  ListItem: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_LISTITEM,
+     Ci.nsIAccessibleRole.ROLE_TERM]),
+
+  Link: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_LINK],
+    function Link_match(aAccessible)
+    {
+      // We want to ignore anchors, only focus real links.
+      let state = {};
+      let extraState = {};
+      aAccessible.getState(state, extraState);
+      if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
+        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      } else {
+        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+      }
+    }),
+
+  List: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_LIST,
+     Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST]),
+
+  PageTab: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_PAGETAB]),
+
+  RadioButton: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
+     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM]),
+
+  Separator: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_SEPARATOR]),
+
+  Table: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_TABLE]),
+
+  Checkbox: new BaseTraversalRule(
+    [Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
+     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM])
+};
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -24,28 +24,39 @@ var Utils = {
     if (!this._AccRetrieval) {
       this._AccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
         getService(Ci.nsIAccessibleRetrieval);
     }
 
     return this._AccRetrieval;
   },
 
+  set MozBuildApp(value) {
+    this._buildApp = value;
+  },
+
   get MozBuildApp() {
     if (!this._buildApp)
       this._buildApp = this._buildAppMap[Services.appinfo.ID];
     return this._buildApp;
   },
 
   get OS() {
     if (!this._OS)
       this._OS = Services.appinfo.OS;
     return this._OS;
   },
 
+  get ScriptName() {
+    if (!this._ScriptName)
+      this._ScriptName =
+        (Services.appinfo.processType == 2) ? 'AccessFuContent' : 'AccessFu';
+    return this._ScriptName;
+  },
+
   get AndroidSdkVersion() {
     if (!this._AndroidSdkVersion) {
       let shellVersion = Services.sysinfo.get('shellVersion') || '';
       let matches = shellVersion.match(/\((\d+)\)$/);
       if (matches)
         this._AndroidSdkVersion = parseInt(matches[1]);
       else
         this._AndroidSdkVersion = 15; // Most useful in desktop debugging.
@@ -66,34 +77,51 @@ var Utils = {
         return aWindow.gBrowser;
       case 'b2g':
         return aWindow.shell;
       default:
         return null;
     }
   },
 
+  getCurrentBrowser: function getCurrentBrowser(aWindow) {
+    if (this.MozBuildApp == 'b2g')
+      return this.getBrowserApp(aWindow).contentBrowser;
+    return this.getBrowserApp(aWindow).selectedBrowser;
+  },
+
   getCurrentContentDoc: function getCurrentContentDoc(aWindow) {
-    if (this.MozBuildApp == "b2g")
-      return this.getBrowserApp(aWindow).contentBrowser.contentDocument;
-    return this.getBrowserApp(aWindow).selectedBrowser.contentDocument;
+    return this.getCurrentBrowser(aWindow).contentDocument;
   },
 
-  getAllDocuments: function getAllDocuments(aWindow) {
-    let doc = this.AccRetrieval.
-      getAccessibleFor(this.getCurrentContentDoc(aWindow)).
-      QueryInterface(Ci.nsIAccessibleDocument);
-    let docs = [];
-    function getAllDocuments(aDocument) {
-      docs.push(aDocument.DOMDocument);
-      for (let i = 0; i < aDocument.childDocumentCount; i++)
-        getAllDocuments(aDocument.getChildDocumentAt(i));
+  getMessageManager: function getMessageManager(aBrowser) {
+    try {
+      return aBrowser.QueryInterface(Ci.nsIFrameLoaderOwner).
+         frameLoader.messageManager;
+    } catch (x) {
+      Logger.error(x);
+      return null;
     }
-    getAllDocuments(doc);
-    return docs;
+  },
+
+  getAllMessageManagers: function getAllMessageManagers(aWindow) {
+    let messageManagers = [];
+
+    for (let i = 0; i < aWindow.messageManager.childCount; i++)
+      messageManagers.push(aWindow.messageManager.getChildAt(i));
+
+    let remoteframes = this.getCurrentContentDoc(aWindow).
+      querySelectorAll('iframe[remote=true]');
+
+    for (let i = 0; i < remoteframes.length; ++i)
+      messageManagers.push(this.getMessageManager(remoteframes[i]));
+
+    Logger.info(messageManagers.length);
+
+    return messageManagers;
   },
 
   getViewport: function getViewport(aWindow) {
     switch (this.MozBuildApp) {
       case 'mobile/android':
         return aWindow.BrowserApp.selectedTab.getViewport();
       default:
         return null;
@@ -118,93 +146,16 @@ var Utils = {
       try {
         return doc.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
       } catch (x) {
         doc = doc.parentDocument;
       }
     }
 
     return null;
-  },
-
-  scroll: function scroll(aWindow, aPage, aHorizontal) {
-    for each (let doc in this.getAllDocuments(aWindow)) {
-      // First see if we could scroll a window.
-      let win = doc.defaultView;
-      if (!aHorizontal && win.scrollMaxY &&
-          ((aPage > 0 && win.scrollY < win.scrollMaxY) ||
-           (aPage < 0 && win.scrollY > 0))) {
-        win.scroll(0, win.innerHeight);
-        return true;
-      } else if (aHorizontal && win.scrollMaxX &&
-                 ((aPage > 0 && win.scrollX < win.scrollMaxX) ||
-                  (aPage < 0 && win.scrollX > 0))) {
-        win.scroll(win.innerWidth, 0);
-        return true;
-      }
-
-      // Second, try to scroll main section or current target if there is no
-      // main section.
-      let main = doc.querySelector('[role=main]') ||
-        doc.querySelector(':target');
-
-      if (main) {
-        if ((!aHorizontal && main.clientHeight < main.scrollHeight) ||
-          (aHorizontal && main.clientWidth < main.scrollWidth)) {
-          let s = win.getComputedStyle(main);
-          if (!aHorizontal) {
-            if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
-              main.scrollTop += aPage * main.clientHeight;
-              return true;
-            }
-          } else {
-            if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
-              main.scrollLeft += aPage * main.clientWidth;
-              return true;
-            }
-          }
-        }
-      }
-    }
-
-    return false;
-  },
-
-  changePage: function changePage(aWindow, aPage) {
-    for each (let doc in this.getAllDocuments(aWindow)) {
-      // Get current main section or active target.
-      let main = doc.querySelector('[role=main]') ||
-        doc.querySelector(':target');
-      if (!main)
-        continue;
-
-      let mainAcc = this.AccRetrieval.getAccessibleFor(main);
-      if (!mainAcc)
-        continue;
-
-      let controllers = mainAcc.
-        getRelationByType(Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
-
-      for (var i=0; controllers.targetsCount > i; i++) {
-        let controller = controllers.getTarget(i);
-        // If the section has a controlling slider, it should be considered
-        // the page-turner.
-        if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
-          // Sliders are controlled with ctrl+right/left. I just decided :)
-          let evt = doc.createEvent("KeyboardEvent");
-          evt.initKeyEvent('keypress', true, true, null,
-                           true, false, false, false,
-                           (aPage > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
-          controller.DOMNode.dispatchEvent(evt);
-          return true;
-        }
-      }
-    }
-
-    return false;
   }
 };
 
 var Logger = {
   DEBUG: 0,
   INFO: 1,
   WARNING: 2,
   ERROR: 3,
@@ -212,17 +163,18 @@ var Logger = {
 
   logLevel: 1, // INFO;
 
   log: function log(aLogLevel) {
     if (aLogLevel < this.logLevel)
       return;
 
     let message = Array.prototype.slice.call(arguments, 1).join(' ');
-    dump('[AccessFu] ' + this._LEVEL_NAMES[aLogLevel] + ' ' + message + '\n');
+    dump('[' + Utils.ScriptName + '] ' +
+         this._LEVEL_NAMES[aLogLevel] +' ' + message + '\n');
   },
 
   info: function info() {
     this.log.apply(
       this, [this.INFO].concat(Array.prototype.slice.call(arguments)));
   },
 
   debug: function debug() {
deleted file mode 100644
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ /dev/null
@@ -1,434 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-var EXPORTED_SYMBOLS = ['VirtualCursorController'];
-
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-
-function BaseTraversalRule(aRoles, aMatchFunc) {
-  this._matchRoles = aRoles;
-  this._matchFunc = aMatchFunc;
-}
-
-BaseTraversalRule.prototype = {
-    getMatchRoles: function BaseTraversalRule_getmatchRoles(aRules) {
-      aRules.value = this._matchRoles;
-      return aRules.value.length;
-    },
-
-    preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
-    Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
-
-    match: function BaseTraversalRule_match(aAccessible)
-    {
-      if (this._matchFunc)
-        return this._matchFunc(aAccessible);
-
-      return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-    },
-
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
-};
-
-var TraversalRules = {
-  Simple: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_MENUITEM,
-     Ci.nsIAccessibleRole.ROLE_LINK,
-     Ci.nsIAccessibleRole.ROLE_PAGETAB,
-     Ci.nsIAccessibleRole.ROLE_GRAPHIC,
-     // XXX: Find a better solution for ROLE_STATICTEXT.
-     // It allows to filter list bullets but at the same time it
-     // filters CSS generated content too as an unwanted side effect.
-     // Ci.nsIAccessibleRole.ROLE_STATICTEXT,
-     Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
-     Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
-     Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
-     Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
-     Ci.nsIAccessibleRole.ROLE_COMBOBOX,
-     Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
-     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
-     Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
-     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
-     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
-     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
-     Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
-     Ci.nsIAccessibleRole.ROLE_ENTRY],
-    function Simple_match(aAccessible) {
-      switch (aAccessible.role) {
-      case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
-        // We don't want to ignore the subtree because this is often
-        // where the list box hangs out.
-        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-      case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
-        {
-          // Nameless text leaves are boring, skip them.
-          let name = aAccessible.name;
-          if (name && name.trim())
-            return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-          else
-            return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-        }
-      case Ci.nsIAccessibleRole.ROLE_LINK:
-        // If the link has children we should land on them instead.
-        // Image map links don't have children so we need to match those.
-        if (aAccessible.childCount == 0)
-          return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-        else
-          return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-      default:
-        // Ignore the subtree, if there is one. So that we don't land on
-        // the same content that was already presented by its parent.
-        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
-          Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
-      }
-    }
-  ),
-
-  Anchor: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LINK],
-    function Anchor_match(aAccessible)
-    {
-      // We want to ignore links, only focus named anchors.
-      let state = {};
-      let extraState = {};
-      aAccessible.getState(state, extraState);
-      if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
-        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-      } else {
-        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-      }
-    }),
-
-  Button: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
-     Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
-     Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
-     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
-     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID]),
-
-  Combobox: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_COMBOBOX,
-     Ci.nsIAccessibleRole.ROLE_LISTBOX]),
-
-  Entry: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_ENTRY,
-     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT]),
-
-  FormElement: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
-     Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
-     Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
-     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
-     Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID,
-     Ci.nsIAccessibleRole.ROLE_COMBOBOX,
-     Ci.nsIAccessibleRole.ROLE_LISTBOX,
-     Ci.nsIAccessibleRole.ROLE_ENTRY,
-     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
-     Ci.nsIAccessibleRole.ROLE_PAGETAB,
-     Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
-     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
-     Ci.nsIAccessibleRole.ROLE_SLIDER,
-     Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
-     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM]),
-
-  Graphic: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_GRAPHIC]),
-
-  Heading: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_HEADING]),
-
-  ListItem: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LISTITEM,
-     Ci.nsIAccessibleRole.ROLE_TERM]),
-
-  Link: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LINK],
-    function Link_match(aAccessible)
-    {
-      // We want to ignore anchors, only focus real links.
-      let state = {};
-      let extraState = {};
-      aAccessible.getState(state, extraState);
-      if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
-        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-      } else {
-        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-      }
-    }),
-
-  List: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LIST,
-     Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST]),
-
-  PageTab: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_PAGETAB]),
-
-  RadioButton: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
-     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM]),
-
-  Separator: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_SEPARATOR]),
-
-  Table: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_TABLE]),
-
-  Checkbox: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
-     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM])
-};
-
-var VirtualCursorController = {
-  exploreByTouch: false,
-  editableState: 0,
-
-  attach: function attach(aWindow) {
-    this.chromeWin = aWindow;
-    this.chromeWin.document.addEventListener('keypress', this, true);
-    this.chromeWin.addEventListener('mozAccessFuGesture', this, true);
-  },
-
-  detach: function detach() {
-    this.chromeWin.document.removeEventListener('keypress', this, true);
-    this.chromeWin.removeEventListener('mozAccessFuGesture', this, true);
-  },
-
-  handleEvent: function VirtualCursorController_handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case 'keypress':
-        this._handleKeypress(aEvent);
-        break;
-      case 'mozAccessFuGesture':
-        this._handleGesture(aEvent);
-        break;
-    }
-  },
-
-  _handleGesture: function _handleGesture(aEvent) {
-    let document = Utils.getCurrentContentDoc(this.chromeWin);
-    let detail = aEvent.detail;
-    Logger.info('Gesture', detail.type,
-                '(fingers: ' + detail.touches.length + ')');
-
-    if (detail.touches.length == 1) {
-      switch (detail.type) {
-        case 'swiperight':
-          this.moveForward(document, aEvent.shiftKey);
-          break;
-        case 'swipeleft':
-          this.moveBackward(document, aEvent.shiftKey);
-          break;
-        case 'doubletap':
-          this.activateCurrent(document);
-          break;
-        case 'explore':
-          this.moveToPoint(document, detail.x, detail.y);
-          break;
-      }
-    }
-
-    if (detail.touches.length == 3) {
-      switch (detail.type) {
-        case 'swiperight':
-          if (!Utils.scroll(this.chromeWin, -1, true))
-            Utils.changePage(this.chromeWin, -1);
-          break;
-        case 'swipedown':
-          Utils.scroll(this.chromeWin, -1);
-          break;
-        case 'swipeleft':
-          if (!Utils.scroll(this.chromeWin, 1, true))
-            Utils.changePage(this.chromeWin, 1);
-        case 'swipeup':
-          Utils.scroll(this.chromeWin, 1);
-          break;
-      }
-    }
-  },
-
-  _handleKeypress: function _handleKeypress(aEvent) {
-    let document = Utils.getCurrentContentDoc(this.chromeWin);
-    let target = aEvent.target;
-
-    // Ignore keys with modifiers so the content could take advantage of them.
-    if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
-      return;
-
-    switch (aEvent.keyCode) {
-      case 0:
-        // an alphanumeric key was pressed, handle it separately.
-        // If it was pressed with either alt or ctrl, just pass through.
-        // If it was pressed with meta, pass the key on without the meta.
-        if (this.editableState)
-          return;
-
-        let key = String.fromCharCode(aEvent.charCode);
-        let methodName = '', rule = {};
-        try {
-          [methodName, rule] = this.keyMap[key];
-        } catch (x) {
-          return;
-        }
-        this[methodName](document, false, rule);
-        break;
-      case aEvent.DOM_VK_RIGHT:
-        if (this.editableState) {
-          if (target.selectionEnd != target.textLength)
-            // Don't move forward if caret is not at end of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveForward(document, aEvent.shiftKey);
-        break;
-      case aEvent.DOM_VK_LEFT:
-        if (this.editableState) {
-          if (target.selectionEnd != 0)
-            // Don't move backward if caret is not at start of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveBackward(document, aEvent.shiftKey);
-        break;
-      case aEvent.DOM_VK_UP:
-        if (this.editableState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) {
-          if (target.selectionEnd != 0)
-            // Don't blur content if caret is not at start of text area.
-            return;
-          else
-            target.blur();
-        }
-
-        if (Utils.MozBuildApp == 'mobile/android')
-          // Return focus to native Android browser chrome.
-          Cc['@mozilla.org/android/bridge;1'].
-            getService(Ci.nsIAndroidBridge).handleGeckoMessage(
-              JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
-        break;
-      case aEvent.DOM_VK_RETURN:
-      case aEvent.DOM_VK_ENTER:
-        if (this.editableState)
-          return;
-        this.activateCurrent(document);
-        break;
-      default:
-        return;
-    }
-
-    aEvent.preventDefault();
-    aEvent.stopPropagation();
-  },
-
-  moveToPoint: function moveToPoint(aDocument, aX, aY) {
-    Utils.getVirtualCursor(aDocument).moveToPoint(TraversalRules.Simple,
-                                                  aX, aY, true);
-  },
-
-  moveForward: function moveForward(aDocument, aLast, aRule) {
-    let virtualCursor = Utils.getVirtualCursor(aDocument);
-    if (aLast) {
-      virtualCursor.moveLast(TraversalRules.Simple);
-    } else {
-      try {
-        virtualCursor.moveNext(aRule || TraversalRules.Simple);
-      } catch (x) {
-        this.moveCursorToObject(
-          virtualCursor,
-          Utils.AccRetrieval.getAccessibleFor(aDocument.activeElement), aRule);
-      }
-    }
-  },
-
-  moveBackward: function moveBackward(aDocument, aFirst, aRule) {
-    let virtualCursor = Utils.getVirtualCursor(aDocument);
-    if (aFirst) {
-      virtualCursor.moveFirst(TraversalRules.Simple);
-    } else {
-      try {
-        virtualCursor.movePrevious(aRule || TraversalRules.Simple);
-      } catch (x) {
-        this.moveCursorToObject(
-          virtualCursor,
-          Utils.AccRetrieval.getAccessibleFor(aDocument.activeElement), aRule);
-      }
-    }
-  },
-
-  activateCurrent: function activateCurrent(document) {
-    let virtualCursor = Utils.getVirtualCursor(document);
-    let acc = virtualCursor.position;
-
-    if (acc.actionCount > 0) {
-      acc.doAction(0);
-    } else {
-      // XXX Some mobile widget sets do not expose actions properly
-      // (via ARIA roles, etc.), so we need to generate a click.
-      // Could possibly be made simpler in the future. Maybe core
-      // engine could expose nsCoreUtiles::DispatchMouseEvent()?
-      let docAcc = Utils.AccRetrieval.getAccessibleFor(this.chromeWin.document);
-      let docX = {}, docY = {}, docW = {}, docH = {};
-      docAcc.getBounds(docX, docY, docW, docH);
-
-      let objX = {}, objY = {}, objW = {}, objH = {};
-      acc.getBounds(objX, objY, objW, objH);
-
-      let x = Math.round((objX.value - docX.value) + objW.value / 2);
-      let y = Math.round((objY.value - docY.value) + objH.value / 2);
-
-      let cwu = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
-        getInterface(Ci.nsIDOMWindowUtils);
-      cwu.sendMouseEventToWindow('mousedown', x, y, 0, 1, 0, false);
-      cwu.sendMouseEventToWindow('mouseup', x, y, 0, 1, 0, false);
-    }
-  },
-
-  moveCursorToObject: function moveCursorToObject(aVirtualCursor,
-                                                  aAccessible, aRule) {
-    aVirtualCursor.moveNext(aRule || TraversalRules.Simple, aAccessible, true);
-  },
-
-  keyMap: {
-    a: ['moveForward', TraversalRules.Anchor],
-    A: ['moveBackward', TraversalRules.Anchor],
-    b: ['moveForward', TraversalRules.Button],
-    B: ['moveBackward', TraversalRules.Button],
-    c: ['moveForward', TraversalRules.Combobox],
-    C: ['moveBackward', TraversalRules.Combobox],
-    e: ['moveForward', TraversalRules.Entry],
-    E: ['moveBackward', TraversalRules.Entry],
-    f: ['moveForward', TraversalRules.FormElement],
-    F: ['moveBackward', TraversalRules.FormElement],
-    g: ['moveForward', TraversalRules.Graphic],
-    G: ['moveBackward', TraversalRules.Graphic],
-    h: ['moveForward', TraversalRules.Heading],
-    H: ['moveBackward', TraversalRules.Heading],
-    i: ['moveForward', TraversalRules.ListItem],
-    I: ['moveBackward', TraversalRules.ListItem],
-    k: ['moveForward', TraversalRules.Link],
-    K: ['moveBackward', TraversalRules.Link],
-    l: ['moveForward', TraversalRules.List],
-    L: ['moveBackward', TraversalRules.List],
-    p: ['moveForward', TraversalRules.PageTab],
-    P: ['moveBackward', TraversalRules.PageTab],
-    r: ['moveForward', TraversalRules.RadioButton],
-    R: ['moveBackward', TraversalRules.RadioButton],
-    s: ['moveForward', TraversalRules.Separator],
-    S: ['moveBackward', TraversalRules.Separator],
-    t: ['moveForward', TraversalRules.Table],
-    T: ['moveBackward', TraversalRules.Table],
-    x: ['moveForward', TraversalRules.Checkbox],
-    X: ['moveBackward', TraversalRules.Checkbox]
-  }
-};
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/content-script.js
@@ -0,0 +1,253 @@
+/* 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/. */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+var Cr = Components.results;
+
+Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+Cu.import('resource://gre/modules/accessibility/EventManager.jsm');
+Cu.import('resource://gre/modules/accessibility/TraversalRules.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+Logger.debug('content-script.js');
+
+function virtualCursorControl(aMessage) {
+  if (Logger.logLevel >= Logger.DEBUG)
+    Logger.debug(aMessage.name, JSON.stringify(aMessage.json));
+
+  try {
+    let vc = Utils.getVirtualCursor(content.document);
+    let origin = aMessage.json.origin;
+    if (origin != 'child') {
+      if (forwardMessage(vc, aMessage))
+        return;
+    }
+
+    let details = aMessage.json;
+    let rule = TraversalRules[details.rule];
+    let moved = 0;
+    switch (details.action) {
+    case 'moveFirst':
+    case 'moveLast':
+      moved = vc[details.action](rule);
+      break;
+    case 'moveNext':
+    case 'movePrevious':
+      try {
+        if (origin == 'parent' && vc.position == null) {
+          if (details.action == 'moveNext')
+            moved = vc.moveFirst(rule);
+          else
+            moved = vc.moveLast(rule);
+        } else {
+          moved = vc[details.action](rule);
+        }
+      } catch (x) {
+        moved = vc.moveNext(rule, content.document.activeElement, true);
+      }
+      break;
+    case 'moveToPoint':
+      moved = vc.moveToPoint(rule, details.x, details.y, true);
+      break;
+    case 'presentLastPivot':
+      EventManager.presentLastPivot();
+      break;
+    default:
+      break;
+    }
+
+    if (moved == true) {
+      forwardMessage(vc, aMessage);
+    } else if (moved == false && details.action != 'moveToPoint') {
+      if (origin == 'parent') {
+        vc.position = null;
+      }
+      aMessage.json.origin = 'child';
+      sendAsyncMessage('AccessFu:VirtualCursor', aMessage.json);
+    }
+  } catch (x) {
+    Logger.error(x);
+  }
+}
+
+function forwardMessage(aVirtualCursor, aMessage) {
+  try {
+    let acc = aVirtualCursor.position;
+    if (acc && acc.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
+      let mm = Utils.getMessageManager(acc.DOMNode);
+      mm.addMessageListener(aMessage.name, virtualCursorControl);
+      aMessage.json.origin = 'parent';
+      // XXX: OOP content's screen offset is 0,
+      // so we remove the real screen offset here.
+      aMessage.json.x -= content.mozInnerScreenX;
+      aMessage.json.y -= content.mozInnerScreenY;
+      mm.sendAsyncMessage(aMessage.name, aMessage.json);
+      return true;
+    }
+  } catch (x) {
+    Logger.error(x);
+  }
+  return false;
+}
+
+function activateCurrent(aMessage) {
+  Logger.debug('activateCurrent');
+  function activateAccessible(aAccessible) {
+    if (aAccessible.actionCount > 0) {
+      aAccessible.doAction(0);
+    } else {
+      // XXX Some mobile widget sets do not expose actions properly
+      // (via ARIA roles, etc.), so we need to generate a click.
+      // Could possibly be made simpler in the future. Maybe core
+      // engine could expose nsCoreUtiles::DispatchMouseEvent()?
+      let docAcc = Utils.AccRetrieval.getAccessibleFor(content.document);
+      let docX = {}, docY = {}, docW = {}, docH = {};
+      docAcc.getBounds(docX, docY, docW, docH);
+
+      let objX = {}, objY = {}, objW = {}, objH = {};
+      aAccessible.getBounds(objX, objY, objW, objH);
+
+      let x = Math.round((objX.value - docX.value) + objW.value / 2);
+      let y = Math.round((objY.value - docY.value) + objH.value / 2);
+
+      let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).
+        getInterface(Ci.nsIDOMWindowUtils);
+      cwu.sendMouseEventToWindow('mousedown', x, y, 0, 1, 0, false);
+      cwu.sendMouseEventToWindow('mouseup', x, y, 0, 1, 0, false);
+    }
+  }
+
+  let vc = Utils.getVirtualCursor(content.document);
+  if (!forwardMessage(vc, aMessage))
+    activateAccessible(vc.position);
+}
+
+function scroll(aMessage) {
+  let vc = Utils.getVirtualCursor(content.document);
+
+  function tryToScroll() {
+    let horiz = aMessage.json.horizontal;
+    let page = aMessage.json.page;
+
+    // Search up heirarchy for scrollable element.
+    let acc = vc.position;
+    while (acc) {
+      let elem = acc.DOMNode;
+
+      // We will do window scrolling next.
+      if (elem == content.document)
+        break;
+
+      if (!horiz && elem.clientHeight < elem.scrollHeight) {
+        let s = content.getComputedStyle(elem);
+        if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
+          elem.scrollTop += page * elem.clientHeight;
+          return true;
+        }
+      }
+
+      if (horiz) {
+        if (elem.clientWidth < elem.scrollWidth) {
+          let s = content.getComputedStyle(elem);
+          if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
+            elem.scrollLeft += page * elem.clientWidth;
+            return true;
+          }
+        }
+
+        let controllers = acc.
+          getRelationByType(
+            Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
+        for (let i = 0; controllers.targetsCount > i; i++) {
+          let controller = controllers.getTarget(i);
+          // If the section has a controlling slider, it should be considered
+          // the page-turner.
+          if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
+            // Sliders are controlled with ctrl+right/left. I just decided :)
+            let evt = content.document.createEvent('KeyboardEvent');
+            evt.initKeyEvent(
+              'keypress', true, true, null,
+              true, false, false, false,
+              (page > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
+            controller.DOMNode.dispatchEvent(evt);
+            return true;
+          }
+        }
+      }
+      acc = acc.parent;
+    }
+
+    // Scroll window.
+    if (!horiz && content.scrollMaxY &&
+        ((page > 0 && content.scrollY < content.scrollMaxY) ||
+         (page < 0 && content.scrollY > 0))) {
+      content.scroll(0, content.innerHeight);
+      return true;
+    } else if (horiz && content.scrollMaxX &&
+               ((page > 0 && content.scrollX < content.scrollMaxX) ||
+                (page < 0 && content.scrollX > 0))) {
+      content.scroll(content.innerWidth, 0);
+      return true;
+    }
+
+    return false;
+  }
+
+  if (aMessage.json.origin != 'child') {
+    if (forwardMessage(vc, aMessage))
+      return;
+  }
+
+  if (!tryToScroll()) {
+    // Failed to scroll anything in this document. Try in parent document.
+    aMessage.json.origin = 'child';
+    sendAsyncMessage('AccessFu:Scroll', aMessage.json);
+  }
+}
+
+addMessageListener('AccessFu:VirtualCursor', virtualCursorControl);
+addMessageListener('AccessFu:Activate', activateCurrent);
+addMessageListener('AccessFu:Scroll', scroll);
+
+addMessageListener(
+  'AccessFu:Start',
+  function(m) {
+    if (m.json.buildApp)
+      Utils.MozBuildApp = m.json.buildApp;
+
+    EventManager.start(
+      function sendMessage(aName, aDetails) {
+        sendAsyncMessage(aName, aDetails);
+      });
+
+    docShell.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIWebProgress).
+      addProgressListener(EventManager,
+                          (Ci.nsIWebProgress.NOTIFY_STATE_ALL |
+                           Ci.nsIWebProgress.NOTIFY_LOCATION));
+    addEventListener('scroll', EventManager, true);
+    addEventListener('resize', EventManager, true);
+    // XXX: Ideally this would be an a11y event. Bug #742280.
+    addEventListener('DOMActivate', EventManager, true);
+  });
+
+addMessageListener(
+  'AccessFu:Stop',
+  function(m) {
+    Logger.debug('AccessFu:Stop');
+
+    EventManager.stop();
+
+    docShell.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIWebProgress).
+      removeProgressListener(EventManager);
+    removeEventListener('scroll', EventManager, true);
+    removeEventListener('resize', EventManager, true);
+    // XXX: Ideally this would be an a11y event. Bug #742280.
+    removeEventListener('DOMActivate', EventManager, true);
+  });
+
+sendAsyncMessage('AccessFu:Ready');
--- a/accessible/src/jsat/jar.mn
+++ b/accessible/src/jsat/jar.mn
@@ -1,6 +1,7 @@
 # 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/.
 
 toolkit.jar:
     content/global/accessibility/AccessFu.css (AccessFu.css)
+    content/global/accessibility/content-script.js (content-script.js)
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -52,8 +52,11 @@ LOCAL_INCLUDES += \
   -I$(srcdir)/../html \