Merge m-c to fig. [r=karma]
authorSriram Ramasubramanian <sriram@mozilla.com>
Wed, 03 Jul 2013 17:08:31 -0700
changeset 156289 49e0f1320f140e265d766baa9f18778f726264b6
parent 156288 b689792b6fd2070e77774ce4a65e9bb52cad0a1d (current diff)
parent 149639 38767daf33dd71d71264de5ca052592ccf2c05b8 (diff)
child 156290 e4ab0a67ccaef00a58ced6023d7f684c3f047279
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarma
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fig. [r=karma]
accessible/src/jsat/UtteranceGenerator.jsm
accessible/tests/mochitest/jsat/utterance.js
addon-sdk/source/lib/sdk/content/content-proxy.js
addon-sdk/source/test/test-content-proxy.js
b2g/config/panda-gaia-central/README
b2g/config/panda-gaia-central/config.json
b2g/config/panda-gaia-central/releng-pandaboard.tt
b2g/config/panda-gaia-central/sources.xml
browser/base/content/test/browser_CTPScriptPlugin.js
browser/base/content/test/browser_bug818009.js
browser/base/content/test/plugin_bug818009.html
browser/base/content/test/plugin_test_noScriptNoPopup.html
browser/base/content/test/plugin_test_scriptedNoPopup1.html
browser/base/content/test/plugin_test_scriptedNoPopup2.html
browser/base/content/test/plugin_test_scriptedNoPopup3.html
browser/base/content/test/plugin_test_scriptedPopup1.html
browser/base/content/test/plugin_test_scriptedPopup2.html
browser/base/content/test/plugin_test_scriptedPopup3.html
browser/branding/aurora/content/about-wordmark.png
browser/branding/nightly/content/about-wordmark.png
browser/branding/official/content/about-wordmark.png
browser/branding/unofficial/content/about-wordmark.png
browser/components/sidebar/Makefile.in
browser/config/mozconfigs/linux32/qt
browser/config/mozconfigs/linux32/rpm
browser/config/mozconfigs/linux64/rpm
browser/config/mozconfigs/macosx-universal/shark
browser/devtools/debugger/DebuggerUI.jsm
browser/devtools/debugger/test/browser_dbg_createRemote.js
browser/devtools/netmonitor/test/browser_net_post-data.js
browser/devtools/profiler/ProfilerController.jsm
browser/devtools/profiler/ProfilerHelpers.jsm
browser/devtools/profiler/ProfilerPanel.jsm
browser/devtools/profiler/cmd-profiler.jsm
browser/devtools/profiler/test/browser_profiler_bug_830664_multiple_profiles.js
browser/devtools/profiler/test/browser_profiler_profiles.js
browser/devtools/webconsole/test/test-bug-595934-dom-html-external.html
browser/devtools/webconsole/test/test-bug-595934-dom-html-external.js
browser/devtools/webconsole/test/test-bug-595934-dom-html.html
browser/fuel/src/Makefile.in
browser/metro/base/content/pages/aboutCrash.xhtml
browser/metro/base/tests/mochitest/browser_plugin_input.html
browser/metro/base/tests/mochitest/browser_plugin_input_keyboard.js
browser/metro/base/tests/mochitest/browser_plugin_input_mouse.js
browser/metro/theme/images/back.png
browser/metro/theme/images/forward.png
browser/metro/theme/images/panel-light.png
browser/metro/theme/images/reload.png
browser/metro/theme/images/stop-hdpi.png
browser/themes/linux/devtools/arrows.png
browser/themes/linux/devtools/goto-mdn.png
browser/themes/linux/devtools/tools-icons-small.png
browser/themes/linux/social/chat-close.png
browser/themes/osx/devtools/arrows.png
browser/themes/osx/devtools/floating-scrollbars-light.css
browser/themes/osx/devtools/floating-scrollbars.css
browser/themes/osx/devtools/goto-mdn.png
browser/themes/osx/devtools/toolbarbutton-close.png
browser/themes/osx/devtools/tools-icons-small.png
browser/themes/osx/linen-pattern.png
browser/themes/osx/social/chat-close.png
browser/themes/windows/devtools/arrows.png
browser/themes/windows/devtools/goto-mdn.png
browser/themes/windows/devtools/toolbarbutton-close.png
browser/themes/windows/devtools/tools-icons-small.png
browser/themes/windows/social/chat-close.png
build/manifestparser.py
build/pgo/Makefile.in
build/pgo/blueprint/Makefile.in
build/pgo/blueprint/moz.build
build/pgo/genpgocert.py.in
build/pgo/js-input/Makefile.in
build/pgo/js-input/moz.build
build/pgo/moz.build
build/tests/filter-example.ini
build/tests/fleem
build/tests/include-example.ini
build/tests/include/bar.ini
build/tests/include/crash-handling
build/tests/include/flowers
build/tests/include/foo.ini
build/tests/mozmill-example.ini
build/tests/mozmill-restart-example.ini
build/tests/path-example.ini
build/tests/test.py
build/tests/test_expressionparser.txt
build/tests/test_manifestparser.txt
build/tests/test_testmanifest.txt
config/nsStaticComponents.cpp.in
config/nsStaticComponents.h
content/events/src/nsDOMGamepad.cpp
content/events/src/nsDOMGamepad.h
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLFormElement.h
content/html/content/test/test_bug664299.html
content/media/test/test_too_many_elements.html
content/media/test/use_large_cache.js
content/media/webaudio/GainProcessor.h
content/media/webaudio/WaveTable.cpp
content/media/webaudio/WaveTable.h
content/media/webaudio/test/test_audioBufferSourceNodeGain.html
content/media/webaudio/test/test_audioBufferSourceNodeGainInLoop.html
content/media/webaudio/test/test_delayNodeWithGainAlternate.html
content/media/webaudio/test/test_waveTable.html
content/media/webspeech/recognition/nsIDOMSpeechRecognitionError.idl
content/xbl/src/nsXBLInsertionPoint.cpp
content/xbl/src/nsXBLInsertionPoint.h
content/xul/content/crashtests/236853.rdf
content/xul/content/crashtests/236853.xul
content/xul/templates/src/crashtests/329335-1.xul
content/xul/templates/src/crashtests/330010-1.rdf
content/xul/templates/src/crashtests/330010-1.xul
content/xul/templates/src/crashtests/397148-1.xul
docshell/base/nsIDocShellHistory.idl
dom/icc/interfaces/nsIDOMICCCardLockErrorEvent.idl
dom/indexedDB/nsIIDBFileHandle.idl
dom/interfaces/core/nsIDOMNodeSelector.idl
dom/interfaces/core/nsIDocumentRegister.idl
dom/interfaces/html/nsIDOMHTMLCommandElement.idl
dom/interfaces/svg/nsIDOMGetSVGDocument.idl
dom/interfaces/svg/nsIDOMSVGAnimatedInteger.idl
dom/interfaces/svg/nsIDOMSVGAnimatedLength.idl
dom/interfaces/svg/nsIDOMSVGAnimatedString.idl
dom/interfaces/svg/nsIDOMSVGDocument.idl
dom/messages/Makefile.in
dom/mobilemessage/src/ril/WapPushManager.js
dom/permission/Makefile.in
dom/push/src/Makefile.in
dom/settings/Makefile.in
dom/system/GamepadService.cpp
dom/system/GamepadService.h
dom/tests/mochitest/gamepad/test_gamepad_basic.html
dom/time/nsIDOMTimeManager.idl
dom/webidl/AnonXMLHttpRequest.webidl
dom/webidl/WaveTable.webidl
dom/workers/test/relativeLoad_sub_import.js
dom/workers/test/relativeLoad_sub_worker.js
dom/workers/test/relativeLoad_sub_worker2.js
gfx/2d/ScaledFontFreetype.cpp
gfx/2d/ScaledFontFreetype.h
gfx/2d/unittest/GTestMain.cpp
gfx/layers/TestTiledLayerBuffer.cpp
gfx/skia/include/core/SkMMapStream.h
gfx/skia/include/core/SkRandom.h
gfx/skia/include/core/SkTDLinkedList.h
gfx/skia/include/effects/SkSingleInputImageFilter.h
gfx/skia/include/gpu/GrCacheID.h
gfx/skia/include/gpu/GrCustomStage.h
gfx/skia/include/gpu/GrCustomStageUnitTest.h
gfx/skia/include/gpu/GrInstanceCounter.h
gfx/skia/include/gpu/GrMatrix.h
gfx/skia/include/gpu/GrProgramStageFactory.h
gfx/skia/include/gpu/GrSamplerState.h
gfx/skia/include/gpu/GrScalar.h
gfx/skia/include/gpu/SkGpuCanvas.h
gfx/skia/include/gpu/gl/SkGLContext.h
gfx/skia/include/images/SkFlipPixelRef.h
gfx/skia/include/images/SkJpegUtility.h
gfx/skia/include/ports/SkStream_Win.h
gfx/skia/include/views/SkOSWindow_wxwidgets.h
gfx/skia/patches/0001-Bug-777614-Re-add-our-SkUserConfig.h-r-nrc.patch
gfx/skia/patches/0001-Bug-803063-Skia-cross-compilation-for-Windows-fails-.patch
gfx/skia/patches/0004-Bug-777614-Re-apply-bug-719872-Fix-crash-on-Android-.patch
gfx/skia/patches/0005-Bug-777614-Re-apply-bug-687188-Expand-the-gradient-c.patch
gfx/skia/patches/0009-Bug-777614-Re-apply-759683-Handle-compilers-that-don.patch
gfx/skia/patches/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch
gfx/skia/patches/0011-Bug-839347-no-anon-namespace-around-SkNO_RETURN_HINT.patch
gfx/skia/patches/0012-Bug-751418-Add-our-own-GrUserConfig-r-mattwoodrow.patch
gfx/skia/patches/0013-Bug-751418-Fix-compile-error-on-gcc-in-Skia-GL-r-mat.patch
gfx/skia/patches/0018-Bug-817356-PPC-defines.patch
gfx/skia/src/core/SkConcaveToTriangles.cpp
gfx/skia/src/core/SkConcaveToTriangles.h
gfx/skia/src/core/SkMMapStream.cpp
gfx/skia/src/effects/SkRectShape.cpp
gfx/skia/src/effects/SkSingleInputImageFilter.cpp
gfx/skia/src/gpu/GrCustomStage.cpp
gfx/skia/src/gpu/GrGpuVertex.h
gfx/skia/src/gpu/GrMatrix.cpp
gfx/skia/src/gpu/GrPathRendererChain.h
gfx/skia/src/gpu/GrRandom.h
gfx/skia/src/gpu/GrTDArray.h
gfx/skia/src/gpu/GrTLList.h
gfx/skia/src/gpu/SkGpuCanvas.cpp
gfx/skia/src/gpu/android/GrGLCreateNativeInterface_android.cpp
gfx/skia/src/gpu/android/SkNativeGLContext_android.cpp
gfx/skia/src/gpu/app-android.cpp
gfx/skia/src/gpu/effects/GrColorTableEffect.cpp
gfx/skia/src/gpu/effects/GrColorTableEffect.h
gfx/skia/src/gpu/gl/GrGLContextInfo.cpp
gfx/skia/src/gpu/gl/GrGLContextInfo.h
gfx/skia/src/gpu/gl/GrGLProgramStage.cpp
gfx/skia/src/gpu/gl/GrGLProgramStage.h
gfx/skia/src/gpu/gl/SkGLContext.cpp
gfx/skia/src/gpu/gr_hello_world.cpp
gfx/skia/src/gpu/ios/GrGLDefaultInterface_iOS.cpp
gfx/skia/src/images/SkFDStream.cpp
gfx/skia/src/images/SkFlipPixelRef.cpp
gfx/skia/src/ports/SkFontDescriptor.cpp
gfx/skia/src/ports/SkFontDescriptor.h
gfx/skia/src/ports/SkFontHost_FONTPATH.cpp
gfx/skia/src/ports/SkFontHost_android_old.cpp
gfx/skia/src/ports/SkFontHost_ascender.cpp
gfx/skia/src/ports/SkFontHost_freetype_mac.cpp
gfx/skia/src/ports/SkFontHost_mac_atsui.cpp
gfx/skia/src/ports/SkFontHost_mac_coretext.cpp
gfx/skia/src/ports/SkFontHost_simple.cpp
gfx/skia/src/ports/SkFontHost_tables.cpp
gfx/skia/src/ports/SkImageRef_ashmem.cpp
gfx/skia/src/ports/SkImageRef_ashmem.h
gfx/skia/src/views/SkWidget.cpp
gfx/skia/src/views/animated/SkListView.cpp
gfx/skia/src/views/animated/SkListWidget.cpp
gfx/tests/gfxTestCocoaHelper.h
gfx/tests/gfxTestCocoaHelper.mm
ipc/chromium/src/base/at_exit_unittest.cc
ipc/chromium/src/base/atomicops_unittest.cc
ipc/chromium/src/base/command_line_unittest.cc
ipc/chromium/src/base/condition_variable_unittest.cc
ipc/chromium/src/base/data_pack_unittest.cc
ipc/chromium/src/base/debug_util_unittest.cc
ipc/chromium/src/base/directory_watcher_unittest.cc
ipc/chromium/src/base/field_trial_unittest.cc
ipc/chromium/src/base/file_descriptor_shuffle_unittest.cc
ipc/chromium/src/base/file_path_unittest.cc
ipc/chromium/src/base/file_util_unittest.cc
ipc/chromium/src/base/file_version_info_unittest.cc
ipc/chromium/src/base/histogram_unittest.cc
ipc/chromium/src/base/hmac_unittest.cc
ipc/chromium/src/base/idletimer_unittest.cc
ipc/chromium/src/base/lazy_instance_unittest.cc
ipc/chromium/src/base/linked_ptr_unittest.cc
ipc/chromium/src/base/mac_util_unittest.cc
ipc/chromium/src/base/message_loop_unittest.cc
ipc/chromium/src/base/object_watcher_unittest.cc
ipc/chromium/src/base/observer_list_unittest.cc
ipc/chromium/src/base/path_service_unittest.cc
ipc/chromium/src/base/pe_image_unittest.cc
ipc/chromium/src/base/pickle_unittest.cc
ipc/chromium/src/base/pr_time_unittest.cc
ipc/chromium/src/base/process_util_unittest.cc
ipc/chromium/src/base/rand_util_unittest.cc
ipc/chromium/src/base/ref_counted_unittest.cc
ipc/chromium/src/base/scoped_bstr_win_unittest.cc
ipc/chromium/src/base/scoped_comptr_win_unittest.cc
ipc/chromium/src/base/scoped_ptr_unittest.cc
ipc/chromium/src/base/scoped_temp_dir_unittest.cc
ipc/chromium/src/base/scoped_variant_win_unittest.cc
ipc/chromium/src/base/shared_memory_unittest.cc
ipc/chromium/src/base/simple_thread_unittest.cc
ipc/chromium/src/base/singleton_unittest.cc
ipc/chromium/src/base/stack_container_unittest.cc
ipc/chromium/src/base/stats_table_unittest.cc
ipc/chromium/src/base/string_escape_unittest.cc
ipc/chromium/src/base/string_piece_unittest.cc
ipc/chromium/src/base/string_tokenizer_unittest.cc
ipc/chromium/src/base/string_util_unittest.cc
ipc/chromium/src/base/sys_info_unittest.cc
ipc/chromium/src/base/sys_string_conversions_unittest.cc
ipc/chromium/src/base/system_monitor_unittest.cc
ipc/chromium/src/base/thread_collision_warner_unittest.cc
ipc/chromium/src/base/thread_local_storage_unittest.cc
ipc/chromium/src/base/thread_local_unittest.cc
ipc/chromium/src/base/thread_unittest.cc
ipc/chromium/src/base/time_unittest.cc
ipc/chromium/src/base/time_win_unittest.cc
ipc/chromium/src/base/timer_unittest.cc
ipc/chromium/src/base/tracked_objects_unittest.cc
ipc/chromium/src/base/tuple_unittest.cc
ipc/chromium/src/base/values_unittest.cc
ipc/chromium/src/base/version_unittest.cc
ipc/chromium/src/base/waitable_event_unittest.cc
ipc/chromium/src/base/waitable_event_watcher_unittest.cc
ipc/chromium/src/base/watchdog_unittest.cc
ipc/chromium/src/base/win_util_unittest.cc
ipc/chromium/src/base/wmi_util_unittest.cc
ipc/chromium/src/base/word_iterator_unittest.cc
ipc/chromium/src/base/worker_pool_linux_unittest.cc
ipc/chromium/src/base/worker_pool_unittest.cc
ipc/chromium/src/chrome/common/ipc_message_utils.cc
ipc/chromium/src/testing/gtest/include/gtest/gtest-death-test.h
ipc/chromium/src/testing/gtest/include/gtest/gtest-message.h
ipc/chromium/src/testing/gtest/include/gtest/gtest-param-test.h
ipc/chromium/src/testing/gtest/include/gtest/gtest-param-test.h.pump
ipc/chromium/src/testing/gtest/include/gtest/gtest-spi.h
ipc/chromium/src/testing/gtest/include/gtest/gtest-test-part.h
ipc/chromium/src/testing/gtest/include/gtest/gtest-typed-test.h
ipc/chromium/src/testing/gtest/include/gtest/gtest.h
ipc/chromium/src/testing/gtest/include/gtest/gtest_pred_impl.h
ipc/chromium/src/testing/gtest/include/gtest/gtest_prod.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-filepath.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-internal.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-param-util.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-port.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-string.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-type-util.h
ipc/chromium/src/testing/gtest/include/gtest/internal/gtest-type-util.h.pump
ipc/ipdl/test/cxx/PTestBlockChild.ipdl
ipc/ipdl/test/cxx/TestBlockChild.cpp
ipc/ipdl/test/cxx/TestBlockChild.h
js/ipc/CPOWTypes.h
js/ipc/ContextWrapperChild.h
js/ipc/ContextWrapperParent.h
js/ipc/ObjectWrapperChild.cpp
js/ipc/ObjectWrapperChild.h
js/ipc/ObjectWrapperParent.cpp
js/ipc/ObjectWrapperParent.h
js/ipc/PContextWrapper.ipdl
js/ipc/PObjectWrapper.ipdl
js/ipc/jar.mn
js/ipc/tests/adhoc/child.html
js/ipc/tests/adhoc/test.xul
js/ipc/tests/moz.build
js/ipc/tests/unit/cpow_child.js
js/ipc/tests/unit/test_cpow.js
js/src/ion/ParallelArrayAnalysis.cpp
js/src/ion/ParallelArrayAnalysis.h
js/src/jit-test/tests/auto-regress/bug827821.js
js/src/jsapi-tests/testVersion.cpp
js/src/jsdhash.cpp
js/src/jsdhash.h
js/src/jslog2.cpp
js/src/jsprobes.cpp
js/src/jsprobes.h
js/src/jspropertycache.cpp
js/src/jspropertycache.h
js/src/jspropertycacheinlines.h
js/src/parjs-benchmarks/edgesArray1D.js
js/src/parjs-benchmarks/edgesParallelArray1D.js
js/src/parjs-benchmarks/edgesParallelArray2D.js
js/src/tests/most.tests
js/src/tests/narcissus-failures.txt
js/src/tests/narcissus.README
js/src/tests/narcissus.list
js/src/tests/performance.tests
js/src/tests/slow-n.tests
js/src/tests/slow-narcissus.txt
js/src/tests/spidermonkey-gc.tests
js/src/tests/spidermonkey-n.tests
js/src/tests/update-test402.sh
js/xpconnect/tests/unit/bug596580_versioned.js
js/xpconnect/tests/unit/test_bug596580.js
js/xpconnect/tests/unit/test_bug608142.js
layout/base/crashtests/794693.html
layout/base/nsChildIterator.cpp
layout/base/nsChildIterator.h
layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-1-block.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-1-table.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-2-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-2.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-3-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-4-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-4.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-5-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-horiz-5.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-2-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-2.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-3-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-3.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-4-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-4.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-1-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-2-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-2.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-3-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-3.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-4-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-vert-rtl-4.xhtml
layout/reftests/flexbox/flexbox-baseline-align-self-baseline-horiz-1-ref.html
layout/reftests/flexbox/flexbox-baseline-align-self-baseline-horiz-1.html
layout/reftests/flexbox/flexbox-baseline-align-self-baseline-vert-1-ref.html
layout/reftests/flexbox/flexbox-baseline-align-self-baseline-vert-1.html
layout/reftests/flexbox/flexbox-baseline-empty-1-ref.html
layout/reftests/flexbox/flexbox-baseline-empty-1a.html
layout/reftests/flexbox/flexbox-baseline-empty-1b.html
layout/reftests/flexbox/flexbox-baseline-multi-item-horiz-1-ref.html
layout/reftests/flexbox/flexbox-baseline-multi-item-horiz-1.html
layout/reftests/flexbox/flexbox-baseline-multi-item-vert-1-ref.html
layout/reftests/flexbox/flexbox-baseline-multi-item-vert-1.html
layout/reftests/flexbox/flexbox-baseline-single-item-1-ref.html
layout/reftests/flexbox/flexbox-baseline-single-item-1a.html
layout/reftests/flexbox/flexbox-baseline-single-item-1b.html
layout/reftests/flexbox/flexbox-basic-block-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-block-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-block-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-block-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-canvas-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-canvas-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-canvas-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-canvas-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-fieldset-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-fieldset-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-iframe-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-iframe-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-iframe-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-iframe-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-img-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-img-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-img-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-img-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-textarea-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-textarea-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-textarea-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-textarea-vert-1.xhtml
layout/reftests/flexbox/flexbox-basic-video-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-video-horiz-1.xhtml
layout/reftests/flexbox/flexbox-basic-video-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-basic-video-vert-1.xhtml
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-1-ref.xhtml
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-1.xhtml
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-2-ref.html
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-2.html
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-3-ref.html
layout/reftests/flexbox/flexbox-items-as-stacking-contexts-3.html
layout/reftests/flexbox/flexbox-justify-content-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-1.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-2-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-2.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-3-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-3.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-4-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-4.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-5-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-horiz-5.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-1.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-2-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-2.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-3-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-3.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-4-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-4.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-5-ref.xhtml
layout/reftests/flexbox/flexbox-justify-content-vert-5.xhtml
layout/reftests/flexbox/flexbox-margin-auto-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-margin-auto-horiz-1.xhtml
layout/reftests/flexbox/flexbox-margin-auto-horiz-2-ref.xhtml
layout/reftests/flexbox/flexbox-margin-auto-horiz-2.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1-reverse-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1-reverse.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1-rtl-reverse.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1-rtl.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-1.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-2-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-2a.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-2b.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-3-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-3-reverse-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-3-reverse.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-3.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-4-ref.xhtml
layout/reftests/flexbox/flexbox-mbp-horiz-4.xhtml
layout/reftests/flexbox/flexbox-overflow-horiz-1-ref.html
layout/reftests/flexbox/flexbox-overflow-horiz-1.html
layout/reftests/flexbox/flexbox-overflow-horiz-2-ref.html
layout/reftests/flexbox/flexbox-overflow-horiz-2.html
layout/reftests/flexbox/flexbox-overflow-horiz-3-ref.html
layout/reftests/flexbox/flexbox-overflow-horiz-3.html
layout/reftests/flexbox/flexbox-overflow-vert-1-ref.html
layout/reftests/flexbox/flexbox-overflow-vert-1.html
layout/reftests/flexbox/flexbox-overflow-vert-2-ref.html
layout/reftests/flexbox/flexbox-overflow-vert-2.html
layout/reftests/flexbox/flexbox-overflow-vert-3-ref.html
layout/reftests/flexbox/flexbox-overflow-vert-3.html
layout/reftests/flexbox/flexbox-paint-ordering-1-ref.xhtml
layout/reftests/flexbox/flexbox-paint-ordering-1.xhtml
layout/reftests/flexbox/flexbox-paint-ordering-2-ref.xhtml
layout/reftests/flexbox/flexbox-paint-ordering-2.xhtml
layout/reftests/flexbox/flexbox-sizing-horiz-1-ref.xhtml
layout/reftests/flexbox/flexbox-sizing-horiz-1.xhtml
layout/reftests/flexbox/flexbox-sizing-horiz-2-ref.xhtml
layout/reftests/flexbox/flexbox-sizing-horiz-2.xhtml
layout/reftests/flexbox/flexbox-sizing-vert-1-ref.xhtml
layout/reftests/flexbox/flexbox-sizing-vert-1.xhtml
layout/reftests/flexbox/flexbox-sizing-vert-2-ref.xhtml
layout/reftests/flexbox/flexbox-sizing-vert-2.xhtml
layout/reftests/flexbox/flexbox-table-fixup-1-ref.xhtml
layout/reftests/flexbox/flexbox-table-fixup-1a.xhtml
layout/reftests/flexbox/flexbox-table-fixup-1b.xhtml
layout/reftests/flexbox/flexbox-whitespace-handling-1-ref.xhtml
layout/reftests/flexbox/flexbox-whitespace-handling-1a.xhtml
layout/reftests/flexbox/flexbox-whitespace-handling-1b.xhtml
layout/reftests/flexbox/flexbox-whitespace-handling-2-ref.xhtml
layout/reftests/flexbox/flexbox-whitespace-handling-2.xhtml
layout/reftests/flexbox/flexbox-with-pseudo-elements-1-ref.html
layout/reftests/flexbox/flexbox-with-pseudo-elements-1.html
layout/reftests/flexbox/flexbox-with-pseudo-elements-2-ref.html
layout/reftests/flexbox/flexbox-with-pseudo-elements-2.html
layout/reftests/flexbox/flexbox-with-pseudo-elements-3-ref.html
layout/reftests/flexbox/flexbox-with-pseudo-elements-3.html
mobile/android/base/ActivityHandlerHelper.java
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/BrowserApp.java
mobile/android/base/BrowserToolbar.java
mobile/android/base/BrowserToolbarLayout.java
mobile/android/base/Favicons.java
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoViewsFactory.java
mobile/android/base/Makefile.in
mobile/android/base/db/LocalBrowserDB.java
mobile/android/base/home/BookmarksListView.java
mobile/android/base/home/BookmarksPage.java
mobile/android/base/home/TwoLinePageRow.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/color/menu_item_title.xml
mobile/android/base/resources/drawable-hdpi/doorhanger_popup_bg.9.png
mobile/android/base/resources/drawable-large-hdpi-v11/doorhanger_popup_bg.9.png
mobile/android/base/resources/drawable-large-mdpi-v11/doorhanger_popup_bg.9.png
mobile/android/base/resources/drawable-large-xhdpi-v11/doorhanger_popup_bg.9.png
mobile/android/base/resources/drawable-mdpi/doorhanger_popup_bg.9.png
mobile/android/base/resources/drawable-xhdpi/doorhanger_popup_bg.9.png
mobile/android/base/resources/layout-large-v11/browser_toolbar.xml
mobile/android/base/resources/layout-xlarge-land-v11/abouthome_content.xml
mobile/android/base/resources/layout/abouthome_content.xml
mobile/android/base/resources/layout/browser_toolbar.xml
mobile/android/base/resources/layout/doorhangerpopup.xml
mobile/android/base/resources/layout/gecko_app.xml
mobile/android/base/resources/layout/search_engine_row.xml
mobile/android/base/resources/layout/site_identity_popup.xml
mobile/android/base/resources/layout/tabs_panel_header.xml
mobile/android/base/resources/values-v11/styles.xml
mobile/android/base/resources/values-v11/themes.xml
mobile/android/base/resources/values/attrs.xml
mobile/android/base/resources/values/colors.xml
mobile/android/base/resources/values/dimens.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/resources/values/themes.xml
mobile/android/base/resources/xml-v11/preferences_content.xml
mobile/android/base/resources/xml-v11/preferences_general.xml
mobile/android/base/resources/xml-v11/preferences_privacy.xml
mobile/android/base/resources/xml/preferences_datareporting.xml
mobile/android/base/strings.xml.in
mobile/android/base/widget/AboutHome.java
mobile/android/base/widget/TopSitesView.java
mobile/android/modules/Makefile.in
mobile/android/themes/core/images/reader-list-icon-hdpi.png
mobile/android/themes/core/images/reader-list-icon-mdpi.png
mobile/android/themes/core/images/reader-list-icon-xhdpi.png
modules/freetype2/src/sfnt/ttsbit0.c
modules/libjar/objs.mk
netwerk/protocol/http/nsHttp.h
security/manager/locales/en-US/chrome/pippki/validation.dtd
security/manager/pki/resources/content/crlImportDialog.js
security/manager/pki/resources/content/crlImportDialog.xul
security/manager/pki/resources/content/crlManager.js
security/manager/pki/resources/content/crlManager.xul
security/manager/pki/resources/content/pref-crlupdate.js
security/manager/pki/resources/content/pref-crlupdate.xul
security/manager/pki/resources/content/serverCrlNextupdate.js
security/manager/pki/resources/content/serverCrlNextupdate.xul
security/manager/ssl/public/nsICRLInfo.idl
security/manager/ssl/public/nsICRLManager.idl
security/manager/ssl/src/nsCRLInfo.cpp
security/manager/ssl/src/nsCRLInfo.h
security/manager/ssl/src/nsCRLManager.cpp
security/manager/ssl/src/nsCRLManager.h
security/patches/revert-bug-808217.patch
testing/jetpack/README.txt
testing/jetpack/jetpack-location.txt
testing/marionette/marionette-actors.js
testing/marionette/marionette-log-obj.js
testing/mochitest/harness-overlay.xul
testing/mozbase/mozinfo/README.md
testing/mozbase/mozinstall/README.md
testing/xpcshell/xpcshell.ini
toolkit/components/Makefile.in
toolkit/components/console/Makefile.in
toolkit/components/contentprefs/Makefile.in
toolkit/components/mediasniffer/test/unit/test_mediasniffer_webm.js
toolkit/components/microformats/Makefile.in
toolkit/components/prompts/src/Makefile.in
toolkit/components/search/tests/xpcshell/test_engineselect.js
toolkit/components/social/Makefile.in
toolkit/components/thumbnails/Makefile.in
toolkit/components/urlformatter/Makefile.in
toolkit/content/tests/chrome/rtltest/dirtest.xul
toolkit/content/tests/widgets/use_large_cache.js
toolkit/forgetaboutsite/Makefile.in
toolkit/mozapps/handling/Makefile.in
toolkit/mozapps/update/test/chrome/test_0093_stagedBackground.xul
toolkit/mozapps/update/test/chrome/test_0094_stagedServiceBackground.xul
toolkit/mozapps/update/test/chrome/test_0095_restartNotification.xul
toolkit/mozapps/update/test/chrome/test_0096_restartNotification_remote.xul
toolkit/mozapps/update/test/chrome/test_0097_restartNotification_remoteInvalidNumber.xul
xpcom/glue/nsCycleCollectionJSRuntime.h
xpcom/reflect/xptcall/src/md/test/Makefile.in
xpcom/tests/TestSettingsAPI.cpp
--- a/.hgtags
+++ b/.hgtags
@@ -88,8 +88,9 @@ 9697eadafa13b4e9233b39aaeecfeac79503cb54
 6fdf9985acfe6f939da584b2559464ab22264fe7 FIREFOX_AURORA_16_BASE
 fd72dbbd692012224145be1bf13df1d7675fd277 FIREFOX_AURORA_17_BASE
 2704e441363fe2a48e992dfac694482dfd82664a FIREFOX_AURORA_18_BASE
 cf8750abee06cde395c659f8ecd8ae019d7512e3 FIREFOX_AURORA_19_BASE
 5bb309998e7050c9ee80b0147de1e473f008e221 FIREFOX_AURORA_20_BASE
 cc37417e2c284aed960f98ffa479de4ccdd5c7c3 FIREFOX_AURORA_21_BASE
 1c070ab0f9db59f13423b9c1db60419f7a9098f9 FIREFOX_AURORA_22_BASE
 d7ce9089999719d5186595d160f25123a4e63e39 FIREFOX_AURORA_23_BASE
+8d3810543edccf4fbe458178b88dd4a6e420b010 FIREFOX_AURORA_24_BASE
--- a/CLOBBER
+++ b/CLOBBER
@@ -12,12 +12,9 @@
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
-Bug 496923 removed a directory which the non-regenerated js/src/tests/Makefile will still request.
-
-Alternative to clobber is to run ./config.status from the objdir and to
-touch the CLOBBER file in the objdir.
+Bug 848491 - Skia update.
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,25 +33,39 @@ include $(topsrcdir)/config/config.mk
 GARBAGE_DIRS += dist _javagen _profile _tests staticlib
 DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
    config/autoconf.mk \
    unallmakefiles mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 ifndef MOZ_PROFILE_USE
+# One of the first things we do in the build is purge "unknown" files
+# from the object directory. This serves two purposes:
+#
+#   1) Remove files from a previous build no longer accounted for in
+#      this build configuration.
+#
+#   2) Work around poor build system dependencies by forcing some
+#      rebuilds.
+#
+# Ideally #2 does not exist. Our reliance on this aspect should diminish
+# over time.
+#
+# moz.build backend generation simply installs a set of "manifests" into
+# a common directory. Each manifest is responsible for defining files in
+# a specific subdirectory of the object directory. The invoked Python
+# script simply iterates over all the manifests, purging files as
+# necessary. To manage new directories or add files to the manifests,
+# modify the backend generator.
+#
 # We need to explicitly put backend.RecursiveMakeBackend.built here
 # otherwise the rule in rules.mk doesn't run early enough.
 default alldep all:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend.built
-	$(RM) -r $(DIST)/sdk
-	$(RM) -r $(DIST)/include
-	$(RM) -r $(DIST)/private
-	$(RM) -r $(DIST)/public
-	$(RM) -r $(DIST)/bin
-	$(RM) -r _tests
+	$(PYTHON) $(topsrcdir)/config/purge_directories.py -d _build_manifests/purge .
 endif
 
 CLOBBER: $(topsrcdir)/CLOBBER
 	@echo "STOP!  The CLOBBER file has changed."
 	@echo "Please run the build through a sanctioned build wrapper, such as"
 	@echo "'mach build' or client.mk."
 	@exit 1
 
--- a/accessible/public/ia2/Makefile.in
+++ b/accessible/public/ia2/Makefile.in
@@ -2,31 +2,28 @@
 # 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/.
 
 DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
-LIBRARY_NAME  = IA2Marshal
 DEFFILE       = $(win_srcdir)/IA2Marshal.def
 
 IA2DIR        = $(topsrcdir)/other-licenses/ia2
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES       += -DREGISTER_PROXY_DLL
 
 GARBAGE       += $(MIDL_GENERATED_FILES)
 
 FORCE_SHARED_LIB = 1
 
-SRCS_IN_OBJDIR   = 1
-
 # Please keep this list in sync with the moz.build file until the rest of this
 # Makefile is ported over.
 MIDL_INTERFACES = \
   Accessible2.idl \
   Accessible2_2.idl \
   AccessibleAction.idl \
   AccessibleApplication.idl \
   AccessibleComponent.idl \
--- a/accessible/public/ia2/moz.build
+++ b/accessible/public/ia2/moz.build
@@ -43,8 +43,11 @@ interfaces_h = ['%s.h' % x for x in midl
 interfaces_c = ['%s_i.c' % x for x in midl_interfaces]
 
 # The underscore throws off sorting and EXPORTS expects sorted lists.
 interfaces_c.sort()
 
 EXPORTS += headers
 EXPORTS += interfaces_h
 EXPORTS += interfaces_c
+
+LIBRARY_NAME = 'IA2Marshal'
+
--- a/accessible/public/msaa/Makefile.in
+++ b/accessible/public/msaa/Makefile.in
@@ -2,29 +2,26 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
-LIBRARY_NAME	= AccessibleMarshal
 DEFFILE = $(win_srcdir)/AccessibleMarshal.def
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DREGISTER_PROXY_DLL
 
 GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c
 
 FORCE_SHARED_LIB = 1
 
-SRCS_IN_OBJDIR	= 1
-
 CSRCS	= \
 	dlldata.c \
 	ISimpleDOMNode_p.c \
 	ISimpleDOMNode_i.c \
 	ISimpleDOMDocument_p.c \
 	ISimpleDOMDocument_i.c \
 	ISimpleDOMText_p.c \
 	ISimpleDOMText_i.c \
--- a/accessible/public/msaa/moz.build
+++ b/accessible/public/msaa/moz.build
@@ -10,8 +10,10 @@ EXPORTS += [
     'ISimpleDOMDocument.h',
     'ISimpleDOMDocument_i.c',
     'ISimpleDOMNode.h',
     'ISimpleDOMNode_i.c',
     'ISimpleDOMText.h',
     'ISimpleDOMText_i.c',
 ]
 
+LIBRARY_NAME = 'AccessibleMarshal'
+
--- a/accessible/public/nsIAccessibleStates.idl
+++ b/accessible/public/nsIAccessibleStates.idl
@@ -1,16 +1,16 @@
 /* -*- 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 "nsISupports.idl"
 
-[scriptable, uuid(7fe1ee90-edaa-43f1-9f3b-071099b51f08)]
+[scriptable, uuid(f1e0fbb7-fde4-4519-9383-2bcbee428513)]
 interface nsIAccessibleStates : nsISupports
 {
   /**
    * MSAA State flags - used for bitfield. More than 1 allowed.
    */
   const unsigned long  STATE_UNAVAILABLE        = 0x00000001;  // Disabled, maps to opposite of Java ENABLED, Gnome/ATK SENSITIVE?
   const unsigned long  STATE_SELECTED           = 0x00000002;
   const unsigned long  STATE_FOCUSED            = 0x00000004;
@@ -66,10 +66,11 @@ interface nsIAccessibleStates : nsISuppo
   const unsigned long  EXT_STATE_OPAQUE                  = 0x00000100;  // Indicates this object paints every pixel within its rectangular region.
   const unsigned long  EXT_STATE_SINGLE_LINE             = 0x00000200;  // This text object can only contain 1 line of text    
   const unsigned long  EXT_STATE_TRANSIENT               = 0x00000400;  // 
   const unsigned long  EXT_STATE_VERTICAL                = 0x00000800;  // Especially used for sliders and scrollbars  
   const unsigned long  EXT_STATE_STALE                   = 0x00001000;  // Object not dead, but not up-to-date either
   const unsigned long  EXT_STATE_ENABLED                 = 0x00002000;  // A widget that is not unavailable
   const unsigned long  EXT_STATE_SENSITIVE               = 0x00004000;  // Same as ENABLED for now
   const unsigned long  EXT_STATE_EXPANDABLE              = 0x00008000;  // If COLLAPSED or EXPANDED
+  const unsigned long  EXT_STATE_PINNED                  = 0x00010000;  // Indicates object is pinned.
 };
 
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -675,18 +675,17 @@ getRoleCB(AtkObject *aAtkObj)
              msaaRole, ia2Role, nameRule) \
   case roles::geckoRole: \
     aAtkObj->role = atkRole; \
     break;
 
   switch (accWrap->Role()) {
 #include "RoleMap.h"
     default:
-      MOZ_NOT_REACHED("Unknown role.");
-      aAtkObj->role = ATK_ROLE_UNKNOWN;
+      MOZ_CRASH("Unknown role.");
   };
 
 #undef ROLE
 
   return aAtkObj->role;
 }
 
 AtkAttributeSet*
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -4,27 +4,28 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
 # we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
-CFLAGS  	+= $(MOZ_GTK2_CFLAGS)
-CXXFLAGS  += $(MOZ_GTK2_CFLAGS)
+ifdef MOZ_ENABLE_GTK
+CFLAGS      += $(TK_CFLAGS)
+CXXFLAGS    += $(TK_CFLAGS)
+endif
 
 ifdef MOZ_ENABLE_DBUS
 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
 endif
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
--- a/accessible/src/atk/moz.build
+++ b/accessible/src/atk/moz.build
@@ -28,8 +28,10 @@ CPP_SOURCES += [
     'nsMaiInterfaceHypertext.cpp',
     'nsMaiInterfaceImage.cpp',
     'nsMaiInterfaceSelection.cpp',
     'nsMaiInterfaceTable.cpp',
     'nsMaiInterfaceText.cpp',
     'nsMaiInterfaceValue.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_toolkit_s'
+
--- a/accessible/src/atk/nsStateMap.h
+++ b/accessible/src/atk/nsStateMap.h
@@ -20,16 +20,18 @@ The following nsIAccessible states aren'
                          The nsIAccessible state is not currently supported.
   STATE_LINKED:          The object is formatted as a hyperlink. Supported via ATK_ROLE_LINK.
   STATE_EXTSELECTABLE:   Indicates that an object extends its selection.
                          This is supported via STATE_MULTISELECTABLE.
   STATE_PROTECTED:       The object is a password-protected edit control.
                          Supported via ATK_ROLE_PASSWORD_TEXT
   STATE_HASPOPUP:        Object displays a pop-up menu or window when invoked.
                          No ATK equivalent.  The nsIAccessible state is not currently supported.
+  STATE_PINNED:          The object is pinned, usually indicating it is fixed in place and has permanence.
+                         No ATK equivalent.  The nsIAccessible state is not currently supported.
 
 The following ATK states are not supported:
   ATK_STATE_ARMED:       No clear use case, used briefly when button is activated
   ATK_STATE_HAS_TOOLTIP: No clear use case, no IA2 equivalent
   ATK_STATE_ICONIFIED:   Mozilla does not have elements which are collapsable into icons
   ATK_STATE_TRUNCATED:   No clear use case. Indicates that an object's onscreen content is truncated, 
                          e.g. a text value in a spreadsheet cell. No IA2 state.
 ******************************************************************************/
@@ -54,17 +56,17 @@ struct AtkStateMap {
       ++ stateIndex;
       aState >>= 1;
     }
     return stateIndex;  // Returns -1 if not mapped
   }
 };
 
 
-// Map array from cross platform roles to  ATK roles
+// Map array from cross platform states to ATK states
 static const AtkStateMap gAtkStateMap[] = {                     // Cross Platform States
   { kNone,                                    kMapOpposite },   // states::UNAVAILABLE             = 1 << 0
   { ATK_STATE_SELECTED,                       kMapDirectly },   // states::SELECTED                = 1 << 1
   { ATK_STATE_FOCUSED,                        kMapDirectly },   // states::FOCUSED                 = 1 << 2
   { ATK_STATE_PRESSED,                        kMapDirectly },   // states::PRESSED                 = 1 << 3
   { ATK_STATE_CHECKED,                        kMapDirectly },   // states::CHECKED                 = 1 << 4
   { ATK_STATE_INDETERMINATE,                  kMapDirectly },   // states::MIXED                   = 1 << 5
   { kNone,                                    kMapDirectly },   // states::READONLY                = 1 << 6
@@ -103,10 +105,11 @@ static const AtkStateMap gAtkStateMap[] 
   { ATK_STATE_OPAQUE,                         kMapDirectly },   // states::OPAQUE                  = 1 << 39
   { ATK_STATE_SINGLE_LINE,                    kMapDirectly },   // states::SINGLE_LINE             = 1 << 40
   { ATK_STATE_TRANSIENT,                      kMapDirectly },   // states::TRANSIENT               = 1 << 41
   { ATK_STATE_VERTICAL,                       kMapDirectly },   // states::VERTICAL                = 1 << 42
   { ATK_STATE_STALE,                          kMapDirectly },   // states::STALE                   = 1 << 43
   { ATK_STATE_ENABLED,                        kMapDirectly },   // states::ENABLED                 = 1 << 44
   { ATK_STATE_SENSITIVE,                      kMapDirectly },   // states::SENSITIVE               = 1 << 45
   { ATK_STATE_EXPANDABLE,                     kMapDirectly },   // states::EXPANDABLE              = 1 << 46
-  { kNone,                                    kNoSuchState },   //                                 = 1 << 47
+  { kNone,                                    kMapDirectly },   // states::PINNED                  = 1 << 47
+  { kNone,                                    kNoSuchState },   //                                 = 1 << 48
 };
--- a/accessible/src/base/ARIAMap.cpp
+++ b/accessible/src/base/ARIAMap.cpp
@@ -680,17 +680,17 @@ static const EStateRule sWAIUnivStateMap
 struct AttrCharacteristics
 {
   nsIAtom** attributeName;
   const uint8_t characteristics;
 };
 
 static const AttrCharacteristics gWAIUnivAttrMap[] = {
   {&nsGkAtoms::aria_activedescendant,  ATTR_BYPASSOBJ                               },
-  {&nsGkAtoms::aria_atomic,                             ATTR_VALTOKEN | ATTR_GLOBAL },
+  {&nsGkAtoms::aria_atomic,   ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_busy,                               ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_checked,           ATTR_BYPASSOBJ | ATTR_VALTOKEN               }, /* exposes checkable obj attr */
   {&nsGkAtoms::aria_controls,          ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_describedby,       ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_disabled,          ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_dropeffect,                         ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_expanded,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_flowto,            ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
--- a/accessible/src/base/DocManager.cpp
+++ b/accessible/src/base/DocManager.cpp
@@ -350,16 +350,19 @@ DocManager::AddListeners(nsIDocument* aD
 void
 DocManager::RemoveListeners(nsIDocument* aDocument)
 {
   nsPIDOMWindow* window = aDocument->GetWindow();
   if (!window)
     return;
 
   EventTarget* target = window->GetChromeEventHandler();
+  if (!target)
+    return;
+
   nsEventListenerManager* elm = target->GetListenerManager(true);
   elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
                                  dom::TrustedEventsAtCapture());
 
   elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
                                  dom::TrustedEventsAtCapture());
 }
 
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -4,17 +4,16 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_base_s
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
@@ -23,19 +22,21 @@ LOCAL_INCLUDES += \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/style \
   -I$(srcdir)/../../../layout/svg \
   -I$(srcdir)/../../../layout/xul/base/src \
   -I$(srcdir)/../../../layout/xul/tree/ \
+  -I$(srcdir)/../../../ipc/chromium/src \
   $(NULL)
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_ENABLE_GTK
+CXXFLAGS        += $(MOZ_CAIRO_CFLAGS)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../windows/msaa \
   -I$(srcdir)/../windows/ia2 \
--- a/accessible/src/base/States.h
+++ b/accessible/src/base/States.h
@@ -267,14 +267,19 @@ namespace states {
    */
   const uint64_t SENSITIVE = ((uint64_t) 0x1) << 45;
 
   /**
    * The object is expandable, provides a UI to expand/collapse its children
    * @see EXPANDED and COLLAPSED states.
    */
   const uint64_t EXPANDABLE = ((uint64_t) 0x1) << 46;
+
+  /**
+   * The object is pinned, usually indicating it is fixed in place and has permanence.
+   */
+  const uint64_t PINNED = ((uint64_t) 0x1) << 47;
 } // namespace states
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 	
--- a/accessible/src/base/moz.build
+++ b/accessible/src/base/moz.build
@@ -55,8 +55,11 @@ CPP_SOURCES += [
     'TextUpdater.cpp',
     'TreeWalker.cpp',
 ]
 
 if a11y_log:
     CPP_SOURCES += [
         'Logging.cpp',
     ]
+
+LIBRARY_NAME = 'accessibility_base_s'
+
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -125,17 +125,17 @@ nsAccUtils::GetLevelForXULContainerItem(
   return level;
 }
 
 void
 nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
                                        nsIContent *aStartContent,
                                        nsIContent *aTopContent)
 {
-  nsAutoString atomic, live, relevant, busy;
+  nsAutoString live, relevant, busy;
   nsIContent *ancestor = aStartContent;
   while (ancestor) {
 
     // container-relevant attribute
     if (relevant.IsEmpty() &&
         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) &&
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant))
       SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant);
@@ -154,20 +154,21 @@ nsAccUtils::SetLiveContainerAttributes(n
         if (role) {
           SetAccAttr(aAttributes, nsGkAtoms::containerLiveRole,
                      role->ARIARoleString());
         }
       }
     }
 
     // container-atomic attribute
-    if (atomic.IsEmpty() &&
-        HasDefinedARIAToken(ancestor, nsGkAtoms::aria_atomic) &&
-        ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_atomic, atomic))
-      SetAccAttr(aAttributes, nsGkAtoms::containerAtomic, atomic);
+    if (ancestor->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_atomic,
+                              nsGkAtoms::_true, eCaseMatters)) {
+      SetAccAttr(aAttributes, nsGkAtoms::containerAtomic,
+                 NS_LITERAL_STRING("true"));
+    }
 
     // container-busy attribute
     if (busy.IsEmpty() &&
         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_busy) &&
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_busy, busy))
       SetAccAttr(aAttributes, nsGkAtoms::containerBusy, busy);
 
     if (ancestor == aTopContent)
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -192,17 +192,17 @@ nsCoreUtils::GetAccessKeyFor(nsIContent*
 
 nsIContent *
 nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
 {
   if (aContent->IsElement())
     return aContent;
 
   if (aContent->IsNodeOfType(nsINode::eTEXT))
-    return aContent->GetParent();
+    return aContent->GetFlattenedTreeParent();
 
   return nullptr;
 }
 
 nsINode *
 nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset)
 {
   if (aNode && aNode->IsElement()) {
@@ -535,17 +535,17 @@ nsCoreUtils::GetTreeBoxObject(nsIContent
       if (xulElement) {
         nsCOMPtr<nsIBoxObject> box;
         xulElement->GetBoxObject(getter_AddRefs(box));
         nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
         if (treeBox)
           return treeBox.forget();
       }
     }
-    currentContent = currentContent->GetParent();
+    currentContent = currentContent->GetFlattenedTreeParent();
   }
 
   return nullptr;
 }
 
 already_AddRefed<nsITreeColumn>
 nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
 {
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -131,17 +131,17 @@ nsTextEquivUtils::AppendTextEquivFromCon
 
 nsresult
 nsTextEquivUtils::AppendTextEquivFromTextContent(nsIContent *aContent,
                                                  nsAString *aString)
 {
   if (aContent->IsNodeOfType(nsINode::eTEXT)) {
     bool isHTMLBlock = false;
 
-    nsIContent *parentContent = aContent->GetParent();
+    nsIContent *parentContent = aContent->GetFlattenedTreeParent();
     if (parentContent) {
       nsIFrame *frame = parentContent->GetPrimaryFrame();
       if (frame) {
         // If this text is inside a block level frame (as opposed to span
         // level), we need to add spaces around that block's text, so we don't
         // get words jammed together in final name.
         const nsStyleDisplay* display = frame->StyleDisplay();
         if (display->IsBlockOutsideStyle() ||
@@ -389,14 +389,14 @@ nsTextEquivUtils::GetRoleRule(role aRole
 #define ROLE(geckoRole, stringRole, atkRole, \
              macRole, msaaRole, ia2Role, nameRule) \
   case roles::geckoRole: \
     return nameRule;
 
   switch (aRole) {
 #include "RoleMap.h"
     default:
-      MOZ_NOT_REACHED("Unknown role.");
+      MOZ_CRASH("Unknown role.");
   }
 
 #undef ROLE
 }
 
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -821,26 +821,55 @@ Accessible::ChildAtPoint(int32_t aX, int
   // because containing block (see CSS2) for out of flow element (for example,
   // absolutely positioned element) may be different from its DOM parent and
   // therefore accessible for containing block may be different from accessible
   // for DOM parent but GetFrameForPoint() should be called for containing block
   // to get an out of flow element.
   DocAccessible* accDocument = Document();
   NS_ENSURE_TRUE(accDocument, nullptr);
 
-  nsIFrame *frame = accDocument->GetFrame();
-  NS_ENSURE_TRUE(frame, nullptr);
-
-  nsPresContext *presContext = frame->PresContext();
-
-  nsRect screenRect = frame->GetScreenRectInAppUnits();
-  nsPoint offset(presContext->DevPixelsToAppUnits(aX) - screenRect.x,
-                 presContext->DevPixelsToAppUnits(aY) - screenRect.y);
-
-  nsIFrame *foundFrame = nsLayoutUtils::GetFrameForPoint(frame, offset);
+  nsIFrame* rootFrame = accDocument->GetFrame();
+  NS_ENSURE_TRUE(rootFrame, nullptr);
+
+  nsIFrame* startFrame = rootFrame;
+
+  // Check whether the point is at popup content.
+  nsIWidget* rootWidget = rootFrame->GetView()->GetNearestWidget(nullptr);
+  NS_ENSURE_TRUE(rootWidget, nullptr);
+
+  nsIntRect rootRect;
+  rootWidget->GetScreenBounds(rootRect);
+
+  nsMouseEvent dummyEvent(true, NS_MOUSE_MOVE, rootWidget,
+                          nsMouseEvent::eSynthesized);
+  dummyEvent.refPoint = nsIntPoint(aX - rootRect.x, aY - rootRect.y);
+
+  nsIFrame* popupFrame = nsLayoutUtils::
+    GetPopupFrameForEventCoordinates(accDocument->PresContext()->GetRootPresContext(),
+                                     &dummyEvent);
+  if (popupFrame) {
+    // If 'this' accessible is not inside the popup then ignore the popup when
+    // searching an accessible at point.
+    DocAccessible* popupDoc =
+      GetAccService()->GetDocAccessible(popupFrame->GetContent()->OwnerDoc());
+    Accessible* popupAcc =
+      popupDoc->GetAccessibleOrContainer(popupFrame->GetContent());
+    Accessible* popupChild = this;
+    while (popupChild && !popupChild->IsDoc() && popupChild != popupAcc)
+      popupChild = popupChild->Parent();
+
+    if (popupChild == popupAcc)
+      startFrame = popupFrame;
+  }
+
+  nsPresContext* presContext = startFrame->PresContext();
+  nsRect screenRect = startFrame->GetScreenRectInAppUnits();
+    nsPoint offset(presContext->DevPixelsToAppUnits(aX) - screenRect.x,
+                   presContext->DevPixelsToAppUnits(aY) - screenRect.y);
+  nsIFrame* foundFrame = nsLayoutUtils::GetFrameForPoint(startFrame, offset);
 
   nsIContent* content = nullptr;
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   DocAccessible* contentDocAcc = GetAccService()->
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -1372,18 +1372,19 @@ DocAccessible::RecreateAccessible(nsICon
   }
 #endif
 
   // XXX: we shouldn't recreate whole accessible subtree, instead we should
   // subclass hide and show events to handle them separately and implement their
   // coalescence with normal hide and show events. Note, in this case they
   // should be coalesced with normal show/hide events.
 
-  ContentRemoved(aContent->GetParent(), aContent);
-  ContentInserted(aContent->GetParent(), aContent, aContent->GetNextSibling());
+  nsIContent* parent = aContent->GetFlattenedTreeParent();
+  ContentRemoved(parent, aContent);
+  ContentInserted(parent, aContent, aContent->GetNextSibling());
 }
 
 void
 DocAccessible::ProcessInvalidationList()
 {
   // Invalidate children of container accessible for each element in
   // invalidation list. Allow invalidation list insertions while container
   // children are recached.
@@ -1734,20 +1735,43 @@ DocAccessible::UpdateTree(Accessible* aC
   }
 #endif
 
   nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(aContainer);
 
   if (child) {
     updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
   } else {
-    TreeWalker walker(aContainer, aChildNode, true);
+    if (aIsInsert) {
+      TreeWalker walker(aContainer, aChildNode, true);
 
-    while ((child = walker.NextChild()))
-      updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
+      while ((child = walker.NextChild()))
+        updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
+    } else {
+      // aChildNode may not coorespond to a particular accessible, to handle
+      // this we go through all the children of aContainer.  Then if a child
+      // has aChildNode as an ancestor, or does not have the node for
+      // aContainer as an ancestor remove that child of aContainer.  Note that
+      // when we are called aChildNode may already have been removed
+      // from the DOM so we can't expect it to have a parent or what was it's
+      // parent to have it as a child.
+      nsINode* containerNode = aContainer->GetNode();
+      for (uint32_t idx = 0; idx < aContainer->ContentChildCount();) {
+        Accessible* child = aContainer->ContentChildAt(idx);
+        nsINode* childNode = child->GetContent();
+        while (childNode != aChildNode && childNode != containerNode &&
+               (childNode = childNode->GetParentNode()));
+
+        if (childNode != containerNode) {
+          updateFlags |= UpdateTreeInternal(child, false, reorderEvent);
+        } else {
+          idx++;
+        }
+      }
+    }
   }
 
   // Content insertion/removal is not cause of accessible tree change.
   if (updateFlags == eNoAccessible)
     return;
 
   // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
   // if it did.
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -777,18 +777,19 @@ HyperTextAccessible::GetRelativeOffset(n
       -- hyperTextOffset;
     }
   }
 
   return hyperTextOffset;
 }
 
 int32_t
-HyperTextAccessible::FindWordBoundary(int32_t aOffset, nsDirection aDirection,
-                                      EWordMovementType aWordMovementType)
+HyperTextAccessible::FindBoundary(int32_t aOffset, nsDirection aDirection,
+                                  nsSelectionAmount aAmount,
+                                  EWordMovementType aWordMovementType)
 {
   // Convert hypertext offset to frame-relative offset.
   int32_t offsetInFrame = aOffset, notUsedOffset = aOffset;
   nsRefPtr<Accessible> accAtOffset;
   nsIFrame* frameAtOffset =
     GetPosAndText(offsetInFrame, notUsedOffset, nullptr, nullptr,
                   nullptr, getter_AddRefs(accAtOffset));
   if (!frameAtOffset) {
@@ -802,18 +803,18 @@ HyperTextAccessible::FindWordBoundary(in
       return -1;
 
     // We're on the last continuation since we're on the last character.
     frameAtOffset = frameAtOffset->GetLastContinuation();
   }
 
   // Return hypertext offset of the boundary of the found word.
   return GetRelativeOffset(mDoc->PresShell(), frameAtOffset, offsetInFrame,
-                           accAtOffset, eSelectWord, aDirection,
-                           (aWordMovementType == eStartWord),
+                           accAtOffset, aAmount, aDirection,
+                           (aWordMovementType == eStartWord || aAmount == eSelectBeginLine),
                            aWordMovementType);
 }
 
 /*
 Gets the specified text relative to aBoundaryType, which means:
 BOUNDARY_CHAR             The character before/at/after the offset is returned.
 BOUNDARY_WORD_START       From the word start before/at/after the offset to the next word start.
 BOUNDARY_WORD_END         From the word end before/at/after the offset to the next work end.
@@ -1075,18 +1076,39 @@ HyperTextAccessible::GetTextAtOffset(int
     case BOUNDARY_WORD_END:
       // Ignore the spec and follow what WebKitGtk does because Orca expects it,
       // i.e. return a next word at word end offset of the current word
       // (WebKitGtk behavior) instead the current word (AKT spec).
       *aEndOffset = FindWordBoundary(offset, eDirNext, eEndWord);
       *aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);
       return GetText(*aStartOffset, *aEndOffset, aText);
 
-    case BOUNDARY_LINE_START:
-    case BOUNDARY_LINE_END:
+    case BOUNDARY_LINE_START: {
+      // Home key, arrow down and if not on last line then home key.
+      *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
+      *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectLine);
+      int32_t tmpOffset = FindLineBoundary(*aEndOffset, eDirPrevious, eSelectBeginLine);
+      if (tmpOffset != *aStartOffset)
+        *aEndOffset = tmpOffset;
+
+      return GetText(*aStartOffset, *aEndOffset, aText);
+    }
+
+    case BOUNDARY_LINE_END: {
+      // In contrast to word end boundary we follow the spec here. End key,
+      // then up arrow and if not on first line then end key.
+      *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectEndLine);
+      int32_t tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
+      *aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
+      if (*aStartOffset == *aEndOffset)
+        *aStartOffset = 0;
+
+      return GetText(*aStartOffset, *aEndOffset, aText);
+    }
+
     case BOUNDARY_ATTRIBUTE_RANGE:
       return GetTextHelper(eGetAt, aBoundaryType, aOffset,
                            aStartOffset, aEndOffset, aText);
 
     default:
       return NS_ERROR_INVALID_ARG;
   }
 }
@@ -2107,28 +2129,36 @@ HyperTextAccessible::ScrollSubstringToPo
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible public
 
 // Accessible protected
 ENameValueFlag
 HyperTextAccessible::NativeName(nsString& aName)
 {
+  // Check @alt attribute for invalid img elements.
+  bool hasImgAlt = false;
+  if (mContent->IsHTML(nsGkAtoms::img)) {
+    hasImgAlt = mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
+    if (!aName.IsEmpty())
+      return eNameOK;
+  }
+
   ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
   if (!aName.IsEmpty())
     return nameFlag;
 
   // Get name from title attribute for HTML abbr and acronym elements making it
   // a valid name from markup. Otherwise their name isn't picked up by recursive
   // name computation algorithm. See NS_OK_NAME_FROM_TOOLTIP.
   if (IsAbbreviation() &&
       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
     aName.CompressWhitespace();
 
-  return eNameOK;
+  return hasImgAlt ? eNoNameOnPurpose : eNameOK;
 }
 
 void
 HyperTextAccessible::InvalidateChildren()
 {
   mOffsets.Clear();
 
   AccessibleWrap::InvalidateChildren();
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -262,17 +262,36 @@ protected:
 
     return aOffset;
   }
 
   /**
    * Return an offset of the found word boundary.
    */
   int32_t FindWordBoundary(int32_t aOffset, nsDirection aDirection,
-                           EWordMovementType aWordMovementType);
+                           EWordMovementType aWordMovementType)
+  {
+    return FindBoundary(aOffset, aDirection, eSelectWord, aWordMovementType);
+  }
+
+  /**
+   * Return an offset of the found line boundary.
+   */
+  int32_t FindLineBoundary(int32_t aOffset, nsDirection aDirection,
+                           nsSelectionAmount aAmount)
+  {
+    return FindBoundary(aOffset, aDirection, aAmount, eDefaultBehavior);
+  }
+
+  /**
+   * Return an offset of the found word or line boundary. Helper.
+   */
+  int32_t FindBoundary(int32_t aOffset, nsDirection aDirection,
+                       nsSelectionAmount aAmount,
+                       EWordMovementType aWordMovementType = eDefaultBehavior);
 
   /*
    * This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
    * @param aType, eGetBefore, eGetAt, eGetAfter
    * @param aBoundaryType, char/word-start/word-end/line-start/line-end/paragraph/attribute
    * @param aOffset, offset into the hypertext to start from
    * @param *aStartOffset, the resulting start offset for the returned substring
    * @param *aEndOffset, the resulting end offset for the returned substring
--- a/accessible/src/generic/Makefile.in
+++ b/accessible/src/generic/Makefile.in
@@ -4,17 +4,16 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_generic_s
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
@@ -23,17 +22,17 @@ LOCAL_INCLUDES = \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../content/base/src \
   -I$(srcdir)/../../../content/html/content/src \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_ENABLE_GTK
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../windows/msaa \
   $(NULL)
--- a/accessible/src/generic/moz.build
+++ b/accessible/src/generic/moz.build
@@ -22,8 +22,10 @@ CPP_SOURCES += [
     'HyperTextAccessible.cpp',
     'ImageAccessible.cpp',
     'OuterDocAccessible.cpp',
     'RootAccessible.cpp',
     'TableCellAccessible.cpp',
     'TextLeafAccessible.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_generic_s'
+
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -309,16 +309,17 @@ HTMLTableHeaderCellAccessible::NativeRol
     case 0:
       return roles::COLUMNHEADER;
     case 1:
       return roles::ROWHEADER;
   }
 
   // Assume it's columnheader if there are headers in siblings, otherwise
   // rowheader.
+  // This should iterate the flattened tree
   nsIContent* parentContent = mContent->GetParent();
   if (!parentContent) {
     NS_ERROR("Deattached content on alive accessible?");
     return roles::NOTHING;
   }
 
   for (nsIContent* siblingContent = mContent->GetPreviousSibling(); siblingContent;
        siblingContent = siblingContent->GetPreviousSibling()) {
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -5,17 +5,16 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_html_s
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
@@ -24,17 +23,17 @@ LOCAL_INCLUDES = \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../content/base/src \
   -I$(srcdir)/../../../content/html/content/src \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/tables \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_ENABLE_GTK
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../windows/msaa \
   -I$(srcdir)/../windows/ia2 \
--- a/accessible/src/html/moz.build
+++ b/accessible/src/html/moz.build
@@ -12,8 +12,10 @@ CPP_SOURCES += [
     'HTMLFormControlAccessible.cpp',
     'HTMLImageMapAccessible.cpp',
     'HTMLLinkAccessible.cpp',
     'HTMLListAccessible.cpp',
     'HTMLSelectAccessible.cpp',
     'HTMLTableAccessible.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_html_s'
+
--- a/accessible/src/jsat/AccessFu.css
+++ b/accessible/src/jsat/AccessFu.css
@@ -16,24 +16,16 @@
   box-shadow: inset 1px 1px 1px #444;
   display: block;
   box-sizing: border-box;
   width: 100%;
   height: 100%;
   pointer-events: none;
 }
 
-#accessfu-glass {
-  width: 100%;
-  height: 100%;
-  position: fixed;
-  top: 0px;
-  left: 0px;
-}
-
 #announce-box {
   position: fixed;
   width: 7.5em;
   height: 5em;
   top: calc(100% - 50% - 2.5em);
   left: calc(100% - 50% - 3.75em);
   pointer-events: none;
   display: table;
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -36,17 +36,19 @@ this.AccessFu = {
     } catch (x) {
       // Not on Android
       if (Utils.MozBuildApp === 'b2g') {
         aWindow.addEventListener('ContentStart', this, false);
       }
     }
 
     this._activatePref = new PrefCache(
-      'accessibility.accessfu.activate', this._enableOrDisable.bind(this), true);
+      'accessibility.accessfu.activate', this._enableOrDisable.bind(this));
+
+    this._enableOrDisable();
   },
 
   /**
    * Shut down chrome-layer accessibility functionality from the outside.
    */
   detach: function detach() {
     // Avoid disabling twice.
     if (this._enabled) {
@@ -109,16 +111,17 @@ this.AccessFu = {
     TouchAdapter.start();
 
     Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
     Services.obs.addObserver(this, 'in-process-browser-or-app-frame-shown', false);
     Services.obs.addObserver(this, 'Accessibility:NextObject', false);
     Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
     Services.obs.addObserver(this, 'Accessibility:Focus', false);
     Services.obs.addObserver(this, 'Accessibility:ActivateObject', false);
+    Services.obs.addObserver(this, 'Accessibility:MoveCaret', false);
     Utils.win.addEventListener('TabOpen', this);
     Utils.win.addEventListener('TabClose', this);
     Utils.win.addEventListener('TabSelect', this);
 
     if (this.readyCallback) {
       this.readyCallback();
       delete this.readyCallback;
     }
@@ -151,16 +154,17 @@ this.AccessFu = {
     Utils.win.removeEventListener('TabSelect', this);
 
     Services.obs.removeObserver(this, 'remote-browser-frame-shown');
     Services.obs.removeObserver(this, 'in-process-browser-or-app-frame-shown');
     Services.obs.removeObserver(this, 'Accessibility:NextObject');
     Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
     Services.obs.removeObserver(this, 'Accessibility:Focus');
     Services.obs.removeObserver(this, 'Accessibility:ActivateObject');
+    Services.obs.removeObserver(this, 'Accessibility:MoveCaret');
 
     if (this.doneCallback) {
       this.doneCallback();
       delete this.doneCallback;
     }
   },
 
   _enableOrDisable: function _enableOrDisable() {
@@ -270,16 +274,19 @@ this.AccessFu = {
       case 'Accessibility:Focus':
         this._focused = JSON.parse(aData);
         if (this._focused) {
           let mm = Utils.getMessageManager(Utils.CurrentBrowser);
           mm.sendAsyncMessage('AccessFu:VirtualCursor',
                               {action: 'whereIsIt', move: true});
         }
         break;
+      case 'Accessibility:MoveCaret':
+        this.Input.moveCaret(JSON.parse(aData));
+        break;
       case 'remote-browser-frame-shown':
       case 'in-process-browser-or-app-frame-shown':
       {
         let mm = aSubject.QueryInterface(Ci.nsIFrameLoader).messageManager;
         this._handleMessageManager(mm);
         break;
       }
     }
@@ -407,17 +414,17 @@ var Output = {
         highlightBox.style.display = 'block';
 
         break;
       }
       case 'hideBounds':
       {
         let highlightBox = this.highlightBox ? this.highlightBox.get() : null;
         if (highlightBox)
-          highlightBox.get().style.display = 'none';
+          highlightBox.style.display = 'none';
         break;
       }
       case 'showAnnouncement':
       {
         let announceBox = this.announceBox ? this.announceBox.get() : null;
         if (!announceBox) {
           announceBox = Utils.win.document.
             createElementNS('http://www.w3.org/1999/xhtml', 'div');
@@ -461,16 +468,20 @@ var Output = {
       this._bridge.handleGeckoMessage(JSON.stringify(androidEvent));
     }
   },
 
   Haptic: function Haptic(aDetails, aBrowser) {
     Utils.win.navigator.vibrate(aDetails.pattern);
   },
 
+  Braille: function Braille(aDetails, aBrowser) {
+    Logger.debug('Braille output: ' + aDetails.text);
+  },
+
   _adjustBounds: function(aJsonBounds, aBrowser) {
     let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
                           aJsonBounds.right - aJsonBounds.left,
                           aJsonBounds.bottom - aJsonBounds.top);
     let vp = Utils.getViewport(Utils.win) || { zoom: 1.0, offsetY: 0 };
     let root = Utils.win;
     let offset = { left: -root.mozInnerScreenX, top: -root.mozInnerScreenY };
     let scale = 1 / Utils.getPixelsPerCSSPixel(Utils.win);
@@ -526,17 +537,17 @@ var Input = {
   _handleGesture: function _handleGesture(aGesture) {
     let gestureName = aGesture.type + aGesture.touches.length;
     Logger.info('Gesture', aGesture.type,
                 '(fingers: ' + aGesture.touches.length + ')');
 
     switch (gestureName) {
       case 'dwell1':
       case 'explore1':
-        this.moveCursor('moveToPoint', 'Simple', 'gesture',
+        this.moveCursor('moveToPoint', 'SimpleTouch', 'gesture',
                         aGesture.x, aGesture.y);
         break;
       case 'doubletap1':
         this.activateCurrent();
         break;
       case 'doubletaphold1':
         this.sendContextMenuMessage();
         break;
@@ -656,16 +667,28 @@ var Input = {
   moveCursor: function moveCursor(aAction, aRule, aInputType, aX, aY) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:VirtualCursor',
                         {action: aAction, rule: aRule,
                          x: aX, y: aY, origin: 'top',
                          inputType: aInputType});
   },
 
+  moveCaret: function moveCaret(aDetails) {
+    if (!this.editState.editing) {
+      return;
+    }
+
+    aDetails.atStart = this.editState.atStart;
+    aDetails.atEnd = this.editState.atEnd;
+
+    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    mm.sendAsyncMessage('AccessFu:MoveCaret', aDetails);
+  },
+
   activateCurrent: function activateCurrent() {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:Activate', {});
   },
 
   sendContextMenuMessage: function sendContextMenuMessage() {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:ContextMenu', {});
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -2,16 +2,28 @@
  * 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 Ci = Components.interfaces;
 const Cu = Components.utils;
 
+const EVENT_VIRTUALCURSOR_CHANGED = Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED;
+const EVENT_STATE_CHANGE = Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE;
+const EVENT_SCROLLING_START = Ci.nsIAccessibleEvent.EVENT_SCROLLING_START;
+const EVENT_TEXT_CARET_MOVED = Ci.nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
+const EVENT_TEXT_INSERTED = Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED;
+const EVENT_TEXT_REMOVED = Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED;
+const EVENT_FOCUS = Ci.nsIAccessibleEvent.EVENT_FOCUS;
+
+const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
+const ROLE_DOCUMENT = Ci.nsIAccessibleRole.ROLE_DOCUMENT;
+const ROLE_CHROME_WINDOW = Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW;
+
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Services',
   'resource://gre/modules/Services.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
@@ -52,18 +64,17 @@ this.EventManager.prototype = {
         this.addEventListener('scroll', this, true);
         this.addEventListener('resize', this, true);
         // XXX: Ideally this would be an a11y event. Bug #742280.
         this.addEventListener('DOMActivate', this, true);
       }
       this.present(Presentation.tabStateChanged(null, 'newtab'));
 
     } catch (x) {
-      Logger.error('Failed to start EventManager');
-      Logger.logException(x);
+      Logger.logException(x, 'Failed to start EventManager');
     }
   },
 
   // XXX: Stop is not called when the tab is closed (|TabClose| event is too
   // late). It is only called when the AccessFu is disabled explicitly.
   stop: function stop() {
     if (!this._started) {
       return;
@@ -112,72 +123,71 @@ this.EventManager.prototype = {
           window = aEvent.target.defaultView;
         else if (aEvent.target instanceof Ci.nsIDOMElement)
           window = aEvent.target.ownerDocument.defaultView;
         this.present(Presentation.viewportChanged(window));
         break;
       }
       }
     } catch (x) {
-      Logger.error('Error handling DOM event');
-      Logger.logException(x);
+      Logger.logException(x, 'Error handling DOM event');
     }
   },
 
   handleAccEvent: function handleAccEvent(aEvent) {
     if (Logger.logLevel >= Logger.DEBUG)
       Logger.debug('A11yEvent', Logger.eventToString(aEvent),
                    Logger.accessibleToString(aEvent.accessible));
 
     // Don't bother with non-content events in firefox.
     if (Utils.MozBuildApp == 'browser' &&
-        aEvent.eventType != Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED &&
+        aEvent.eventType != EVENT_VIRTUALCURSOR_CHANGED &&
         aEvent.accessibleDocument != Utils.CurrentContentDoc) {
       return;
     }
 
     switch (aEvent.eventType) {
-      case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
+      case EVENT_VIRTUALCURSOR_CHANGED:
       {
         let pivot = aEvent.accessible.
           QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
         let position = pivot.position;
-        if (position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
+        if (position && position.role == ROLE_INTERNAL_FRAME)
           break;
         let event = aEvent.
           QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
         let reason = event.reason;
 
         if (this.editState.editing)
           aEvent.accessibleDocument.takeFocus();
 
         this.present(
           Presentation.pivotChanged(position, event.oldAccessible, reason));
 
         break;
       }
-      case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
+      case EVENT_STATE_CHANGE:
       {
         let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
         if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
             !(event.isExtraState)) {
           this.present(
             Presentation.
               actionInvoked(aEvent.accessible,
                             event.isEnabled ? 'check' : 'uncheck'));
         }
         break;
       }
-      case Ci.nsIAccessibleEvent.EVENT_SCROLLING_START:
+      case EVENT_SCROLLING_START:
       {
         let vc = Utils.getVirtualCursor(aEvent.accessibleDocument);
         vc.moveNext(TraversalRules.Simple, aEvent.accessible, true);
         break;
       }
-      case Ci.nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED:
+      case 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
@@ -200,18 +210,18 @@ this.EventManager.prototype = {
             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:
+      case EVENT_TEXT_INSERTED:
+      case 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 = '';
@@ -225,23 +235,22 @@ this.EventManager.prototype = {
               throw x;
           }
           this.present(Presentation.textChanged(
                          isInserted, event.start, event.length,
                          text, event.modifiedText));
         }
         break;
       }
-      case Ci.nsIAccessibleEvent.EVENT_FOCUS:
+      case 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) {
+        if (acc.role != ROLE_DOCUMENT && doc.role != ROLE_CHROME_WINDOW) {
           let vc = Utils.getVirtualCursor(doc);
           vc.moveNext(TraversalRules.Simple, acc, true);
         }
         break;
       }
     }
   },
 
@@ -416,15 +425,14 @@ const AccessibilityEventObserver = {
           Logger.accessibleToString(event.accessible), "document:",
           Logger.accessibleToString(event.accessibleDocument));
       }
       return;
     }
     try {
       eventManager.handleAccEvent(event);
     } catch (x) {
-      Logger.error('Error handing accessible event');
-      Logger.logException(x);
+      Logger.logException(x, 'Error handing accessible event');
     } finally {
       return;
     }
   }
 };
--- a/accessible/src/jsat/Makefile.in
+++ b/accessible/src/jsat/Makefile.in
@@ -11,19 +11,19 @@ include $(DEPTH)/config/autoconf.mk
 
 INSTALL_TARGETS += ACCESSFU
 
 ACCESSFU_FILES := \
   AccessFu.jsm \
   EventManager.jsm \
   jar.mn \
   Makefile.in \
+  OutputGenerator.jsm \
   Presentation.jsm \
   TouchAdapter.jsm \
   TraversalRules.jsm \
   Utils.jsm \
-  UtteranceGenerator.jsm \
   $(NULL)
 
 ACCESSFU_DEST = $(FINAL_TARGET)/modules/accessibility
 
 include $(topsrcdir)/config/rules.mk
 
rename from accessible/src/jsat/UtteranceGenerator.jsm
rename to accessible/src/jsat/OutputGenerator.jsm
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/OutputGenerator.jsm
@@ -9,210 +9,200 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_CUSTOM = 0x04;
 const NAME_FROM_SUBTREE_RULE = 0x08;
 
-const UTTERANCE_DESC_FIRST = 0;
+const OUTPUT_DESC_FIRST = 0;
+const OUTPUT_DESC_LAST = 1;
+
+const ROLE_LISTITEM = Ci.nsIAccessibleRole.ROLE_LISTITEM;
+const ROLE_STATICTEXT = Ci.nsIAccessibleRole.ROLE_STATICTEXT;
+const ROLE_LINK = Ci.nsIAccessibleRole.ROLE_LINK;
 
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm',
+  'resource://gre/modules/PluralForm.jsm');
+
 
 let gUtteranceOrder = new PrefCache('accessibility.accessfu.utterance');
 
 var gStringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
   getService(Ci.nsIStringBundleService).
   createBundle('chrome://global/locale/AccessFu.properties');
 
-this.EXPORTED_SYMBOLS = ['UtteranceGenerator'];
-
+this.EXPORTED_SYMBOLS = ['UtteranceGenerator', 'BrailleGenerator'];
 
-/**
- * Generates speech utterances from objects, actions and state changes.
- * An utterance is an array of strings.
- *
- * It should not be assumed that flattening an utterance array would create a
- * gramatically correct sentence. For example, {@link genForObject} might
- * return: ['graphic', 'Welcome to my home page'].
- * Each string element in an utterance should be gramatically correct in itself.
- * Another example from {@link genForObject}: ['list item 2 of 5', 'Alabama'].
- *
- * An utterance is ordered from the least to the most important. Speaking the
- * last string usually makes sense, but speaking the first often won't.
- * For example {@link genForAction} might return ['button', 'clicked'] for a
- * clicked event. Speaking only 'clicked' makes sense. Speaking 'button' does
- * not.
- */
-this.UtteranceGenerator = {
-  gActionMap: {
-    jump: 'jumpAction',
-    press: 'pressAction',
-    check: 'checkAction',
-    uncheck: 'uncheckAction',
-    select: 'selectAction',
-    open: 'openAction',
-    close: 'closeAction',
-    switch: 'switchAction',
-    click: 'clickAction',
-    collapse: 'collapseAction',
-    expand: 'expandAction',
-    activate: 'activateAction',
-    cycle: 'cycleAction'
-  },
+this.OutputGenerator = {
 
   /**
-   * Generates an utterance for a PivotContext.
+   * Generates output for a PivotContext.
    * @param {PivotContext} aContext object that generates and caches
    *    context information for a given accessible and its relationship with
    *    another accessible.
    * @return {Array} An array of strings. Depending on the utterance order,
    *    the strings describe the context for an accessible object either
    *    starting from the accessible's ancestry or accessible's subtree.
    */
   genForContext: function genForContext(aContext) {
-    let utterance = [];
-    let addUtterance = function addUtterance(aAccessible) {
-      utterance.push.apply(utterance,
-        UtteranceGenerator.genForObject(aAccessible));
+    let output = [];
+    let self = this;
+    let addOutput = function addOutput(aAccessible) {
+      output.push.apply(output, self.genForObject(aAccessible, aContext));
     };
-    let roleString = Utils.AccRetrieval.getStringRole(aContext.accessible.role);
-    let nameRule = this.roleRuleMap[roleString] || 0;
-    let utteranceOrder = gUtteranceOrder.value || UTTERANCE_DESC_FIRST;
-    // Include subtree if the name is not explicit or the role's name rule is
-    // not the NAME_FROM_SUBTREE_RULE.
-    let includeSubtree = (Utils.getAttributes(aContext.accessible)[
-      'explicit-name'] !== 'true') || !(nameRule & NAME_FROM_SUBTREE_RULE);
+    let ignoreSubtree = function ignoreSubtree(aAccessible) {
+      let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
+      let nameRule = self.roleRuleMap[roleString] || 0;
+      // Ignore subtree if the name is explicit and the role's name rule is the
+      // NAME_FROM_SUBTREE_RULE.
+      return (nameRule & NAME_FROM_SUBTREE_RULE) &&
+        (Utils.getAttributes(aAccessible)['explicit-name'] === 'true');
+    };
+    let outputOrder = typeof gUtteranceOrder.value == 'number' ?
+                      gUtteranceOrder.value : this.defaultOutputOrder;
+    let contextStart = this._getContextStart(aContext);
 
-    if (utteranceOrder === UTTERANCE_DESC_FIRST) {
-      aContext.newAncestry.forEach(addUtterance);
-      addUtterance(aContext.accessible);
-      if (includeSubtree) {
-        aContext.subtreePreorder.forEach(addUtterance);
-      }
+    if (outputOrder === OUTPUT_DESC_FIRST) {
+      contextStart.forEach(addOutput);
+      addOutput(aContext.accessible);
+      [addOutput(node) for
+        (node of aContext.subtreeGenerator(true, ignoreSubtree))];
     } else {
-      if (includeSubtree) {
-        aContext.subtreePostorder.forEach(addUtterance);
-      }
-      addUtterance(aContext.accessible);
-      aContext.newAncestry.reverse().forEach(addUtterance);
+      [addOutput(node) for
+        (node of aContext.subtreeGenerator(false, ignoreSubtree))];
+      addOutput(aContext.accessible);
+      contextStart.reverse().forEach(addOutput);
     }
 
     // Clean up the white space.
     let trimmed;
-    utterance = [trimmed for (word of utterance) if (trimmed = word.trim())];
-
-    return utterance;
+    output = [trimmed for (word of output) if (trimmed = word.trim())];
+    return output;
   },
 
 
   /**
-   * Generates an utterance for an object.
+   * Generates output for an object.
    * @param {nsIAccessible} aAccessible accessible object to generate utterance
    *    for.
+   * @param {PivotContext} aContext object that generates and caches
+   *    context information for a given accessible and its relationship with
+   *    another accessible.
    * @return {Array} Two string array. The first string describes the object
    *    and its states. The second string is the object's name. Whether the
    *    object's description or it's role is included is determined by
    *    {@link roleRuleMap}.
    */
-  genForObject: function genForObject(aAccessible) {
+  genForObject: function genForObject(aAccessible, aContext) {
     let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
-
-    let func = this.objectUtteranceFunctions[roleString] ||
-      this.objectUtteranceFunctions.defaultFunc;
+    let func = this.objectOutputFunctions[
+      OutputGenerator._getOutputName(roleString)] ||
+      this.objectOutputFunctions.defaultFunc;
 
     let flags = this.roleRuleMap[roleString] || 0;
 
     if (aAccessible.childCount == 0)
       flags |= INCLUDE_NAME;
 
     let state = {};
     let extState = {};
     aAccessible.getState(state, extState);
     let states = {base: state.value, ext: extState.value};
 
-    return func.apply(this, [aAccessible, roleString, states, flags]);
+    return func.apply(this, [aAccessible, roleString, states, flags, aContext]);
   },
 
   /**
-   * Generates an utterance for an action performed.
-   * TODO: May become more verbose in the future.
+   * Generates output for an action performed.
    * @param {nsIAccessible} aAccessible accessible object that the action was
    *    invoked in.
    * @param {string} aActionName the name of the action, one of the keys in
    *    {@link gActionMap}.
    * @return {Array} A one string array with the action.
    */
-  genForAction: function genForAction(aObject, aActionName) {
-    return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
-  },
+  genForAction: function genForAction(aObject, aActionName) {},
 
   /**
-   * Generates an utterance for an announcement. Basically attempts to localize
+   * Generates output for an announcement. Basically attempts to localize
    * the announcement string.
    * @param {string} aAnnouncement unlocalized announcement.
    * @return {Array} A one string array with the announcement.
    */
-  genForAnnouncement: function genForAnnouncement(aAnnouncement) {
-    try {
-      return [gStringBundle.GetStringFromName(aAnnouncement)];
-    } catch (x) {
-      return [aAnnouncement];
-    }
-  },
+  genForAnnouncement: function genForAnnouncement(aAnnouncement) {},
 
   /**
-   * Generates an utterance for a tab state change.
+   * Generates output for a tab state change.
    * @param {nsIAccessible} aAccessible accessible object of the tab's attached
    *    document.
    * @param {string} aTabState the tab state name, see
    *    {@link Presenter.tabStateChanged}.
    * @return {Array} The tab state utterace.
    */
-  genForTabStateChange: function genForTabStateChange(aObject, aTabState) {
-    switch (aTabState) {
-      case 'newtab':
-        return [gStringBundle.GetStringFromName('tabNew')];
-      case 'loading':
-        return [gStringBundle.GetStringFromName('tabLoading')];
-      case 'loaded':
-        return [aObject.name || '',
-                gStringBundle.GetStringFromName('tabLoaded')];
-      case 'loadstopped':
-        return [gStringBundle.GetStringFromName('tabLoadStopped')];
-      case 'reload':
-        return [gStringBundle.GetStringFromName('tabReload')];
-      default:
-        return [];
+  genForTabStateChange: function genForTabStateChange(aObject, aTabState) {},
+
+  /**
+   * Generates output for announcing entering and leaving editing mode.
+   * @param {aIsEditing} boolean true if we are in editing mode
+   * @return {Array} The mode utterance
+   */
+  genForEditingMode: function genForEditingMode(aIsEditing) {},
+
+  _getContextStart: function getContextStart(aContext) {},
+
+  _addName: function _addName(aOutput, aAccessible, aFlags) {
+    let name;
+    if (Utils.getAttributes(aAccessible)['explicit-name'] === 'true' ||
+      (aFlags & INCLUDE_NAME)) {
+      name = aAccessible.name;
+    }
+
+    if (name) {
+      let outputOrder = typeof gUtteranceOrder.value == 'number' ?
+                        gUtteranceOrder.value : this.defaultOutputOrder;
+      aOutput[outputOrder === OUTPUT_DESC_FIRST ?
+        'push' : 'unshift'](name);
     }
   },
 
-  /**
-   * Generates an utterance for announcing entering and leaving editing mode.
-   * @param {aIsEditing} boolean true if we are in editing mode
-   * @return {Array} The mode utterance
-   */
-  genForEditingMode: function genForEditingMode(aIsEditing) {
-    return [gStringBundle.GetStringFromName(
-              aIsEditing ? 'editingMode' : 'navigationMode')];
+  _getOutputName: function _getOutputName(aName) {
+    return aName.replace(' ', '');
+  },
+
+  _getLocalizedRole: function _getLocalizedRole(aRoleStr) {},
+
+  _getLocalizedStates: function _getLocalizedStates(aStates) {},
+
+  _getPluralFormString: function _getPluralFormString(aString, aCount) {
+    let str = gStringBundle.GetStringFromName(this._getOutputName(aString));
+    str = PluralForm.get(aCount, str);
+    return str.replace('#1', aCount);
   },
 
   roleRuleMap: {
     'menubar': INCLUDE_DESC,
     'scrollbar': INCLUDE_DESC,
     'grip': INCLUDE_DESC,
     'alert': INCLUDE_DESC | INCLUDE_NAME,
     'menupopup': INCLUDE_DESC,
     'menuitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'tooltip': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'columnheader': NAME_FROM_SUBTREE_RULE,
-    'rowheader': NAME_FROM_SUBTREE_RULE,
+    'columnheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    'rowheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'column': NAME_FROM_SUBTREE_RULE,
     'row': NAME_FROM_SUBTREE_RULE,
+    'cell': INCLUDE_DESC | INCLUDE_NAME,
     'application': INCLUDE_NAME,
     'document': INCLUDE_NAME,
     'grouping': INCLUDE_DESC | INCLUDE_NAME,
     'toolbar': INCLUDE_DESC,
     'table': INCLUDE_DESC | INCLUDE_NAME,
     'link': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'helpballoon': NAME_FROM_SUBTREE_RULE,
     'list': INCLUDE_DESC | INCLUDE_NAME,
@@ -263,45 +253,154 @@ this.UtteranceGenerator = {
     'term': NAME_FROM_SUBTREE_RULE,
     'definition': NAME_FROM_SUBTREE_RULE,
     'key': NAME_FROM_SUBTREE_RULE,
     'image map': INCLUDE_DESC,
     'option': INCLUDE_DESC,
     'listbox': INCLUDE_DESC,
     'definitionlist': INCLUDE_DESC | INCLUDE_NAME},
 
-  objectUtteranceFunctions: {
-    defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
-      let utterance = [];
+  objectOutputFunctions: {
+    _generateBaseOutput: function _generateBaseOutput(aAccessible, aRoleStr, aStates, aFlags) {
+      let output = [];
 
       if (aFlags & INCLUDE_DESC) {
         let desc = this._getLocalizedStates(aStates);
         let roleStr = this._getLocalizedRole(aRoleStr);
         if (roleStr)
           desc.push(roleStr);
-        utterance.push(desc.join(' '));
+        output.push(desc.join(' '));
       }
 
-      this._addName(utterance, aAccessible, aFlags);
+      this._addName(output, aAccessible, aFlags);
 
-      return utterance;
+      return output;
     },
 
     entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
-      let utterance = [];
+      let output = [];
       let desc = this._getLocalizedStates(aStates);
       desc.push(this._getLocalizedRole(
                   (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
                     'textarea' : 'entry'));
 
-      utterance.push(desc.join(' '));
+      output.push(desc.join(' '));
+
+      this._addName(output, aAccessible, aFlags);
+
+      return output;
+    },
+
+    table: function table(aAccessible, aRoleStr, aStates, aFlags) {
+      let output = [];
+      let table;
+      try {
+        table = aAccessible.QueryInterface(Ci.nsIAccessibleTable);
+      } catch (x) {
+        Logger.logException(x);
+        return output;
+      } finally {
+        // Check if it's a layout table, and bail out if true.
+        // We don't want to speak any table information for layout tables.
+        if (table.isProbablyForLayout()) {
+          return output;
+        }
+        let tableColumnInfo = this._getPluralFormString('tableColumnInfo',
+          table.columnCount);
+        let tableRowInfo = this._getPluralFormString('tableRowInfo',
+          table.rowCount);
+        output.push(gStringBundle.formatStringFromName(
+          this._getOutputName('tableInfo'), [this._getLocalizedRole(aRoleStr),
+            tableColumnInfo, tableRowInfo], 3));
+        this._addName(output, aAccessible, aFlags);
+        return output;
+      }
+    }
+  }
+};
+
+/**
+ * Generates speech utterances from objects, actions and state changes.
+ * An utterance is an array of strings.
+ *
+ * It should not be assumed that flattening an utterance array would create a
+ * gramatically correct sentence. For example, {@link genForObject} might
+ * return: ['graphic', 'Welcome to my home page'].
+ * Each string element in an utterance should be gramatically correct in itself.
+ * Another example from {@link genForObject}: ['list item 2 of 5', 'Alabama'].
+ *
+ * An utterance is ordered from the least to the most important. Speaking the
+ * last string usually makes sense, but speaking the first often won't.
+ * For example {@link genForAction} might return ['button', 'clicked'] for a
+ * clicked event. Speaking only 'clicked' makes sense. Speaking 'button' does
+ * not.
+ */
+this.UtteranceGenerator = {
+  __proto__: OutputGenerator,
+
+  defaultOutputOrder: OUTPUT_DESC_FIRST,
 
-      this._addName(utterance, aAccessible, aFlags);
+  gActionMap: {
+    jump: 'jumpAction',
+    press: 'pressAction',
+    check: 'checkAction',
+    uncheck: 'uncheckAction',
+    select: 'selectAction',
+    open: 'openAction',
+    close: 'closeAction',
+    switch: 'switchAction',
+    click: 'clickAction',
+    collapse: 'collapseAction',
+    expand: 'expandAction',
+    activate: 'activateAction',
+    cycle: 'cycleAction'
+  },
+
+  //TODO: May become more verbose in the future.
+  genForAction: function genForAction(aObject, aActionName) {
+    return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
+  },
+
+  genForAnnouncement: function genForAnnouncement(aAnnouncement) {
+    try {
+      return [gStringBundle.GetStringFromName(aAnnouncement)];
+    } catch (x) {
+      return [aAnnouncement];
+    }
+  },
 
-      return utterance;
+  genForTabStateChange: function genForTabStateChange(aObject, aTabState) {
+    switch (aTabState) {
+      case 'newtab':
+        return [gStringBundle.GetStringFromName('tabNew')];
+      case 'loading':
+        return [gStringBundle.GetStringFromName('tabLoading')];
+      case 'loaded':
+        return [aObject.name || '',
+                gStringBundle.GetStringFromName('tabLoaded')];
+      case 'loadstopped':
+        return [gStringBundle.GetStringFromName('tabLoadStopped')];
+      case 'reload':
+        return [gStringBundle.GetStringFromName('tabReload')];
+      default:
+        return [];
+    }
+  },
+
+  genForEditingMode: function genForEditingMode(aIsEditing) {
+    return [gStringBundle.GetStringFromName(
+              aIsEditing ? 'editingMode' : 'navigationMode')];
+  },
+
+  objectOutputFunctions: {
+
+    __proto__: OutputGenerator.objectOutputFunctions,
+
+    defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
+      return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
     },
 
     heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
       let level = {};
       aAccessible.groupPosition(level, {}, {});
       let utterance =
         [gStringBundle.formatStringFromName('headingLevel', [level.value], 1)];
 
@@ -333,40 +432,77 @@ this.UtteranceGenerator = {
     definitionlist: function definitionlist(aAccessible, aRoleStr, aStates, aFlags) {
       return this._getListUtterance
         (aAccessible, aRoleStr, aFlags, aAccessible.childCount / 2);
     },
 
     application: function application(aAccessible, aRoleStr, aStates, aFlags) {
       // Don't utter location of applications, it gets tiring.
       if (aAccessible.name != aAccessible.DOMNode.location)
-        return this.objectUtteranceFunctions.defaultFunc.apply(this,
+        return this.objectOutputFunctions.defaultFunc.apply(this,
           [aAccessible, aRoleStr, aStates, aFlags]);
 
       return [];
+    },
+
+    cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
+      let utterance = [];
+      let cell = aContext.getCellInfo(aAccessible);
+      if (cell) {
+        let desc = [];
+        let addCellChanged = function addCellChanged(aDesc, aChanged, aString, aIndex) {
+          if (aChanged) {
+            aDesc.push(gStringBundle.formatStringFromName(aString,
+              [aIndex + 1], 1));
+          }
+        };
+        let addExtent = function addExtent(aDesc, aExtent, aString) {
+          if (aExtent > 1) {
+            aDesc.push(gStringBundle.formatStringFromName(aString,
+              [aExtent], 1));
+          }
+        };
+        let addHeaders = function addHeaders(aDesc, aHeaders) {
+          if (aHeaders.length > 0) {
+            aDesc.push.apply(aDesc, aHeaders);
+          }
+        };
+
+        addCellChanged(desc, cell.columnChanged, 'columnInfo', cell.columnIndex);
+        addCellChanged(desc, cell.rowChanged, 'rowInfo', cell.rowIndex);
+
+        addExtent(desc, cell.columnExtent, 'spansColumns');
+        addExtent(desc, cell.rowExtent, 'spansRows');
+
+        addHeaders(desc, cell.columnHeaders);
+        addHeaders(desc, cell.rowHeaders);
+
+        utterance.push(desc.join(' '));
+      }
+
+      this._addName(utterance, aAccessible, aFlags);
+      return utterance;
+    },
+
+    columnheader: function columnheader() {
+      return this.objectOutputFunctions.cell.apply(this, arguments);
+    },
+
+    rowheader: function rowheader() {
+      return this.objectOutputFunctions.cell.apply(this, arguments);
     }
   },
 
-  _addName: function _addName(utterance, aAccessible, aFlags) {
-    let name;
-    if (Utils.getAttributes(aAccessible)['explicit-name'] === 'true' ||
-      (aFlags & INCLUDE_NAME)) {
-      name = aAccessible.name;
-    }
-
-    if (name) {
-      let utteranceOrder = gUtteranceOrder.value || UTTERANCE_DESC_FIRST;
-      utterance[utteranceOrder === UTTERANCE_DESC_FIRST ?
-        'push' : 'unshift'](name);
-    }
+  _getContextStart: function _getContextStart(aContext) {
+    return aContext.newAncestry;
   },
 
   _getLocalizedRole: function _getLocalizedRole(aRoleStr) {
     try {
-      return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
+      return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
     } catch (x) {
       return '';
     }
   },
 
   _getLocalizedStates: function _getLocalizedStates(aStates) {
     let stateUtterances = [];
 
@@ -414,8 +550,159 @@ this.UtteranceGenerator = {
       (gStringBundle.formatStringFromName('listItemCount', [aItemCount], 1));
     let utterance = [desc.join(' ')];
 
     this._addName(utterance, aAccessible, aFlags);
 
     return utterance;
   }
 };
+
+
+this.BrailleGenerator = {
+  __proto__: OutputGenerator,
+
+  defaultOutputOrder: OUTPUT_DESC_LAST,
+
+  objectOutputFunctions: {
+
+    __proto__: OutputGenerator.objectOutputFunctions,
+
+    defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
+      let braille = this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
+
+      if (aAccessible.indexInParent === 1 &&
+          aAccessible.parent.role == ROLE_LISTITEM &&
+          aAccessible.previousSibling.role == ROLE_STATICTEXT) {
+        if (aAccessible.parent.parent && aAccessible.parent.parent.DOMNode &&
+            aAccessible.parent.parent.DOMNode.nodeName == 'UL') {
+          braille.unshift('*');
+        } else {
+          braille.unshift(aAccessible.previousSibling.name);
+        }
+      }
+
+      return braille;
+    },
+
+    listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {
+      let braille = [];
+
+      this._addName(braille, aAccessible, aFlags);
+
+      return braille;
+    },
+
+    cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
+      let braille = [];
+      let cell = aContext.getCellInfo(aAccessible);
+      if (cell) {
+        let desc = [];
+        let addHeaders = function addHeaders(aDesc, aHeaders) {
+          if (aHeaders.length > 0) {
+            aDesc.push.apply(aDesc, aHeaders);
+          }
+        };
+
+        desc.push(gStringBundle.formatStringFromName(
+          this._getOutputName('cellInfo'), [cell.columnIndex + 1,
+            cell.rowIndex + 1], 2));
+
+        addHeaders(desc, cell.columnHeaders);
+        addHeaders(desc, cell.rowHeaders);
+        braille.push(desc.join(' '));
+      }
+
+      this._addName(braille, aAccessible, aFlags);
+      return braille;
+    },
+
+    columnheader: function columnheader() {
+      return this.objectOutputFunctions.cell.apply(this, arguments);
+    },
+
+    rowheader: function rowheader() {
+      return this.objectOutputFunctions.cell.apply(this, arguments);
+    },
+
+    statictext: function statictext(aAccessible, aRoleStr, aStates, aFlags) {
+      // Since we customize the list bullet's output, we add the static
+      // text from the first node in each listitem, so skip it here.
+      if (aAccessible.parent.role == ROLE_LISTITEM) {
+        return [];
+      }
+
+      return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
+    },
+
+    _useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aStates, aFlags) {
+      let braille = [];
+
+      let desc = this._getLocalizedStates(aStates);
+      braille.push(desc.join(' '));
+
+      this._addName(braille, aAccessible, aFlags);
+
+      return braille;
+    },
+
+    checkbutton: function checkbutton(aAccessible, aRoleStr, aStates, aFlags) {
+      return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
+    },
+
+    radiobutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
+      return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
+    },
+
+    togglebutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
+      return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
+    }
+  },
+
+  _getContextStart: function _getContextStart(aContext) {
+    if (aContext.accessible.parent.role == ROLE_LINK) {
+      return [aContext.accessible.parent];
+    }
+
+    return [];
+  },
+
+  _getOutputName: function _getOutputName(aName) {
+    return OutputGenerator._getOutputName(aName) + 'Abbr';
+  },
+
+  _getLocalizedRole: function _getLocalizedRole(aRoleStr) {
+    try {
+      return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
+    } catch (x) {
+      try {
+        return gStringBundle.GetStringFromName(
+          OutputGenerator._getOutputName(aRoleStr));
+      } catch (y) {
+        return '';
+      }
+    }
+  },
+
+  _getLocalizedStates: function _getLocalizedStates(aStates) {
+    let stateBraille = [];
+
+    let getCheckedState = function getCheckedState() {
+      let resultMarker = [];
+      let state = aStates.base;
+      let fill = !!(state & Ci.nsIAccessibleStates.STATE_CHECKED) ||
+                 !!(state & Ci.nsIAccessibleStates.STATE_PRESSED);
+
+      resultMarker.push('(');
+      resultMarker.push(fill ? 'x' : ' ');
+      resultMarker.push(')');
+
+      return resultMarker.join('');
+    };
+
+    if (aStates.base & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
+      stateBraille.push(getCheckedState());
+    }
+
+    return stateBraille;
+  }
+
+};
--- a/accessible/src/jsat/Presentation.jsm
+++ b/accessible/src/jsat/Presentation.jsm
@@ -4,18 +4,27 @@
 
 'use strict';
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import('resource://gre/modules/accessibility/UtteranceGenerator.jsm');
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PivotContext',
+  'resource://gre/modules/accessibility/Utils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'UtteranceGenerator',
+  'resource://gre/modules/accessibility/OutputGenerator.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'BrailleGenerator',
+  'resource://gre/modules/accessibility/OutputGenerator.jsm');
 
 this.EXPORTED_SYMBOLS = ['Presentation'];
 
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
@@ -47,17 +56,17 @@ Presenter.prototype = {
    */
   textChanged: function textChanged(aIsInserted, aStartOffset,
                                     aLength, aText,
                                     aModifiedText) {},
 
   /**
    * Text selection has changed. TODO.
    */
-  textSelectionChanged: function textSelectionChanged() {},
+  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {},
 
   /**
    * Selection has changed. TODO.
    * @param {nsIAccessible} aObject the object that has been selected.
    */
   selectionChanged: function selectionChanged(aObject) {},
 
   /**
@@ -141,17 +150,17 @@ VisualPresenter.prototype = {
         type: this.type,
         details: {
           method: 'showBounds',
           bounds: aContext.bounds,
           padding: this.BORDER_PADDING
         }
       };
     } catch (e) {
-      Logger.error('Failed to get bounds: ' + e);
+      Logger.logException(e, 'Failed to get bounds');
       return null;
     }
   },
 
   tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) {
     return this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
   },
 
@@ -191,18 +200,20 @@ AndroidPresenter.prototype = {
   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_VIEW_TEXT_SELECTION_CHANGED: 0x2000,
   ANDROID_ANNOUNCEMENT: 0x4000,
   ANDROID_VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
+  ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: 0x20000,
 
   pivotChanged: function AndroidPresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible)
       return null;
 
     let androidEvents = [];
 
     let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
@@ -214,25 +225,35 @@ AndroidPresenter.prototype = {
     if (isExploreByTouch) {
       // This isn't really used by TalkBack so this is a half-hearted attempt
       // for now.
       androidEvents.push({eventType: this.ANDROID_VIEW_HOVER_EXIT, text: []});
     }
 
     let state = Utils.getStates(aContext.accessible)[0];
 
+    let brailleText = '';
+    if (Utils.AndroidSdkVersion >= 16) {
+      if (!this._braillePresenter) {
+        this._braillePresenter = new BraillePresenter();
+      }
+      brailleText = this._braillePresenter.pivotChanged(aContext, aReason).
+                         details.text;
+    }
+
     androidEvents.push({eventType: (isExploreByTouch) ?
                           this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
                         text: UtteranceGenerator.genForContext(aContext),
                         bounds: aContext.bounds,
                         clickable: aContext.accessible.actionCount > 0,
                         checkable: !!(state &
                                       Ci.nsIAccessibleStates.STATE_CHECKABLE),
                         checked: !!(state &
-                                    Ci.nsIAccessibleStates.STATE_CHECKED)});
+                                    Ci.nsIAccessibleStates.STATE_CHECKED),
+                        brailleText: brailleText});
 
 
     return {
       type: this.type,
       details: androidEvents
     };
   },
 
@@ -278,16 +299,47 @@ AndroidPresenter.prototype = {
       eventDetails.removedCount = aLength;
       eventDetails.beforeText =
         aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
     }
 
     return {type: this.type, details: [eventDetails]};
   },
 
+  textSelectionChanged: function AndroidPresenter_textSelectionChanged(aText, aStart,
+                                                                       aEnd, aOldStart,
+                                                                       aOldEnd) {
+    let androidEvents = [];
+
+    if (Utils.AndroidSdkVersion >= 14) {
+      androidEvents.push({
+        eventType: this.ANDROID_VIEW_TEXT_SELECTION_CHANGED,
+        text: [aText],
+        fromIndex: aStart,
+        toIndex: aEnd,
+        itemCount: aText.length
+      });
+    }
+
+    if (Utils.AndroidSdkVersion >= 16) {
+      let [from, to] = aOldStart < aStart ? [aOldStart, aStart] : [aStart, aOldStart];
+      androidEvents.push({
+        eventType: this.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
+        text: [aText],
+        fromIndex: from,
+        toIndex: to
+      });
+    }
+
+    return {
+      type: this.type,
+      details: androidEvents
+    };
+  },
+
   viewportChanged: function AndroidPresenter_viewportChanged(aWindow) {
     if (Utils.AndroidSdkVersion < 14)
       return null;
 
     return {
       type: this.type,
       details: [{
         eventType: this.ANDROID_VIEW_SCROLLED,
@@ -341,16 +393,29 @@ SpeechPresenter.prototype = {
         actions: [
           {method: 'playEarcon', data: 'tick', options: {}},
           {method: 'speak',
             data: UtteranceGenerator.genForContext(aContext).join(' '),
             options: {enqueue: true}}
         ]
       }
     };
+  },
+
+  actionInvoked: function SpeechPresenter_actionInvoked(aObject, aActionName) {
+    return {
+      type: this.type,
+      details: {
+        actions: [
+          {method: 'speak',
+           data: UtteranceGenerator.genForAction(aObject, aActionName).join(' '),
+           options: {enqueue: false}}
+        ]
+      }
+    };
   }
 };
 
 /**
  * A haptic presenter
  */
 
 this.HapticPresenter = function HapticPresenter() {};
@@ -362,16 +427,39 @@ HapticPresenter.prototype = {
 
   PIVOT_CHANGE_PATTHERN: [20],
 
   pivotChanged: function HapticPresenter_pivotChanged(aContext, aReason) {
     return { type: this.type, details: { pattern: this.PIVOT_CHANGE_PATTHERN } };
   }
 };
 
+/**
+ * A braille presenter
+ */
+
+this.BraillePresenter = function BraillePresenter() {};
+
+BraillePresenter.prototype = {
+  __proto__: Presenter.prototype,
+
+  type: 'Braille',
+
+  pivotChanged: function BraillePresenter_pivotChanged(aContext, aReason) {
+    if (!aContext.accessible) {
+      return null;
+    }
+
+    let text = BrailleGenerator.genForContext(aContext);
+
+    return { type: this.type, details: {text: text.join(' ')} };
+  }
+
+};
+
 this.Presentation = {
   get presenters() {
     delete this.presenters;
     this.presenters = [new VisualPresenter()];
 
     if (Utils.MozBuildApp == 'mobile/android') {
       this.presenters.push(new AndroidPresenter());
     } else {
@@ -398,16 +486,21 @@ this.Presentation = {
   textChanged: function Presentation_textChanged(aIsInserted, aStartOffset,
                                     aLength, aText,
                                     aModifiedText) {
     return [p.textChanged(aIsInserted, aStartOffset, aLength,
                           aText, aModifiedText)
               for each (p in this.presenters)];
   },
 
+  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {
+    return [p.textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd)
+              for each (p in this.presenters)];
+  },
+
   tabStateChanged: function Presentation_tabStateChanged(aDocObj, aPageState) {
     return [p.tabStateChanged(aDocObj, aPageState)
               for each (p in this.presenters)];
   },
 
   viewportChanged: function Presentation_viewportChanged(aWindow) {
     return [p.viewportChanged(aWindow)
               for each (p in this.presenters)];
--- a/accessible/src/jsat/TouchAdapter.jsm
+++ b/accessible/src/jsat/TouchAdapter.jsm
@@ -49,72 +49,99 @@ this.TouchAdapter = {
     this._dwellTimeout = 0;
     this._prevGestures = {};
     this._lastExploreTime = 0;
     this._dpi = Utils.win.QueryInterface(Ci.nsIInterfaceRequestor).
       getInterface(Ci.nsIDOMWindowUtils).displayDPI;
 
     let target = Utils.win;
 
-    if (Utils.MozBuildApp == 'b2g') {
-      this.glass = Utils.win.document.
-        createElementNS('http://www.w3.org/1999/xhtml', 'div');
-      this.glass.id = 'accessfu-glass';
-      Utils.win.document.documentElement.appendChild(this.glass);
-      target = this.glass;
-    }
-
-    for each (let eventType in this.eventsOfInterest) {
+    for (let eventType in this.eventsOfInterest) {
       target.addEventListener(eventType, this, true, true);
     }
 
   },
 
   stop: function TouchAdapter_stop() {
     Logger.info('TouchAdapter.stop');
 
     let target = Utils.win;
 
-    if (Utils.MozBuildApp == 'b2g') {
-      target = this.glass;
-      this.glass.parentNode.removeChild(this.glass);
-    }
-
-    for each (let eventType in this.eventsOfInterest) {
+    for (let eventType in this.eventsOfInterest) {
       target.removeEventListener(eventType, this, true, true);
     }
   },
 
+  /*
+   * A mapping of events we should be intercepting. Entries with a value of
+   * |true| are used for compiling high-level gesture events. Entries with
+   * a value of |false| are cancelled and do not propogate to content.
+   */
   get eventsOfInterest() {
     delete this.eventsOfInterest;
 
-    if ('ontouchstart' in Utils.win) {
-      this.eventsOfInterest = ['touchstart', 'touchmove', 'touchend'];
-      if (Utils.MozBuildApp == 'mobile/android') {
-        this.eventsOfInterest.push.apply(
-          this.eventsOfInterest, ['mouseenter', 'mousemove', 'mouseleave']);
-      }
-    } else {
-      this.eventsOfInterest = ['mousedown', 'mousemove', 'mouseup', 'click'];
+    switch (Utils.widgetToolkit) {
+      case 'gonk':
+        this.eventsOfInterest = {
+          'touchstart' : true,
+          'touchmove' : true,
+          'touchend' : true,
+          'mousedown' : false,
+          'mousemove' : false,
+          'mouseup': false,
+          'click': false };
+        break;
+
+      case 'android':
+        this.eventsOfInterest = {
+          'touchstart' : true,
+          'touchmove' : true,
+          'touchend' : true,
+          'mousemove' : true,
+          'mouseenter' : true,
+          'mouseleave' : true,
+          'mousedown' : false,
+          'mouseup': false,
+          'click': false };
+        break;
+
+      default:
+        this.eventsOfInterest = {
+          'mousemove' : true,
+          'mousedown' : true,
+          'mouseup': true,
+          'click': false };
+        if ('ontouchstart' in Utils.win) {
+          for (let eventType of ['touchstart', 'touchmove', 'touchend']) {
+            this.eventsOfInterest[eventType] = true;
+          }
+        }
+        break;
     }
 
     return this.eventsOfInterest;
   },
 
   handleEvent: function TouchAdapter_handleEvent(aEvent) {
     // Don't bother with chrome mouse events.
     if (Utils.MozBuildApp == 'browser' &&
         aEvent.view.top instanceof Ci.nsIDOMChromeWindow) {
       return;
     }
 
     if (aEvent.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_UNKNOWN) {
       return;
     }
 
+    if (!this.eventsOfInterest[aEvent.type]) {
+      aEvent.preventDefault();
+      aEvent.stopImmediatePropagation();
+      return;
+    }
+
     if (this._delayedEvent) {
       Utils.win.clearTimeout(this._delayedEvent);
       delete this._delayedEvent;
     }
 
     let changedTouches = aEvent.changedTouches || [aEvent];
 
     // XXX: Until bug 77992 is resolved, on desktop we get microseconds
--- a/accessible/src/jsat/TraversalRules.jsm
+++ b/accessible/src/jsat/TraversalRules.jsm
@@ -4,21 +4,58 @@
 
 'use strict';
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
+const FILTER_IGNORE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+const FILTER_MATCH = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+const FILTER_IGNORE_SUBTREE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
+
+const ROLE_MENUITEM = Ci.nsIAccessibleRole.ROLE_MENUITEM;
+const ROLE_LINK = Ci.nsIAccessibleRole.ROLE_LINK;
+const ROLE_PAGETAB = Ci.nsIAccessibleRole.ROLE_PAGETAB;
+const ROLE_GRAPHIC = Ci.nsIAccessibleRole.ROLE_GRAPHIC;
+const ROLE_STATICTEXT = Ci.nsIAccessibleRole.ROLE_STATICTEXT;
+const ROLE_TEXT_LEAF = Ci.nsIAccessibleRole.ROLE_TEXT_LEAF;
+const ROLE_PUSHBUTTON = Ci.nsIAccessibleRole.ROLE_PUSHBUTTON;
+const ROLE_SPINBUTTON = Ci.nsIAccessibleRole.ROLE_SPINBUTTON;
+const ROLE_CHECKBUTTON = Ci.nsIAccessibleRole.ROLE_CHECKBUTTON;
+const ROLE_RADIOBUTTON = Ci.nsIAccessibleRole.ROLE_RADIOBUTTON;
+const ROLE_COMBOBOX = Ci.nsIAccessibleRole.ROLE_COMBOBOX;
+const ROLE_PROGRESSBAR = Ci.nsIAccessibleRole.ROLE_PROGRESSBAR;
+const ROLE_BUTTONDROPDOWN = Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN;
+const ROLE_BUTTONMENU = Ci.nsIAccessibleRole.ROLE_BUTTONMENU;
+const ROLE_CHECK_MENU_ITEM = Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM;
+const ROLE_PASSWORD_TEXT = Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT;
+const ROLE_RADIO_MENU_ITEM = Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM;
+const ROLE_TOGGLE_BUTTON = Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
+const ROLE_ENTRY = Ci.nsIAccessibleRole.ROLE_ENTRY;
+const ROLE_LIST = Ci.nsIAccessibleRole.ROLE_LIST;
+const ROLE_DEFINITION_LIST = Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST;
+const ROLE_LISTITEM = Ci.nsIAccessibleRole.ROLE_LISTITEM;
+const ROLE_BUTTONDROPDOWNGRID = Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID;
+const ROLE_LISTBOX = Ci.nsIAccessibleRole.ROLE_LISTBOX;
+const ROLE_SLIDER = Ci.nsIAccessibleRole.ROLE_SLIDER;
+const ROLE_HEADING = Ci.nsIAccessibleRole.ROLE_HEADING;
+const ROLE_TERM = Ci.nsIAccessibleRole.ROLE_TERM;
+const ROLE_SEPARATOR = Ci.nsIAccessibleRole.ROLE_SEPARATOR;
+const ROLE_TABLE = Ci.nsIAccessibleRole.ROLE_TABLE;
+const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
+
 this.EXPORTED_SYMBOLS = ['TraversalRules'];
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 
+let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
+
 function BaseTraversalRule(aRoles, aMatchFunc) {
   this._matchRoles = aRoles;
   this._matchFunc = aMatchFunc;
 }
 
 BaseTraversalRule.prototype = {
     getMatchRoles: function BaseTraversalRule_getmatchRoles(aRules) {
       aRules.value = this._matchRoles;
@@ -26,190 +63,201 @@ BaseTraversalRule.prototype = {
     },
 
     preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
     Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE |
     Ci.nsIAccessibleTraversalRule.PREFILTER_ARIA_HIDDEN,
 
     match: function BaseTraversalRule_match(aAccessible)
     {
-      if (aAccessible.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
+      if (aAccessible.role == ROLE_INTERNAL_FRAME) {
         return (Utils.getMessageManager(aAccessible.DOMNode)) ?
-          Ci.nsIAccessibleTraversalRule.FILTER_MATCH :
-          Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+          FILTER_MATCH  | FILTER_IGNORE_SUBTREE : FILTER_IGNORE;
       }
 
       if (this._matchFunc)
         return this._matchFunc(aAccessible);
 
-      return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+      return 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,
-   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,
+  [ROLE_MENUITEM,
+   ROLE_LINK,
+   ROLE_PAGETAB,
+   ROLE_GRAPHIC,
+   ROLE_STATICTEXT,
+   ROLE_TEXT_LEAF,
+   ROLE_PUSHBUTTON,
+   ROLE_CHECKBUTTON,
+   ROLE_RADIOBUTTON,
+   ROLE_COMBOBOX,
+   ROLE_PROGRESSBAR,
+   ROLE_BUTTONDROPDOWN,
+   ROLE_BUTTONMENU,
+   ROLE_CHECK_MENU_ITEM,
+   ROLE_PASSWORD_TEXT,
+   ROLE_RADIO_MENU_ITEM,
+   ROLE_TOGGLE_BUTTON,
+   ROLE_ENTRY,
    // Used for traversing in to child OOP frames.
-   Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME];
+   ROLE_INTERNAL_FRAME];
 
 this.TraversalRules = {
   Simple: new BaseTraversalRule(
     gSimpleTraversalRoles,
     function Simple_match(aAccessible) {
       switch (aAccessible.role) {
-      case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
+      case 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:
+        return FILTER_MATCH;
+      case ROLE_TEXT_LEAF:
         {
           // Nameless text leaves are boring, skip them.
           let name = aAccessible.name;
           if (name && name.trim())
-            return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+            return FILTER_MATCH;
           else
-            return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+            return FILTER_IGNORE;
         }
-      case Ci.nsIAccessibleRole.ROLE_LINK:
+      case 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;
+          return FILTER_MATCH;
         else
-          return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-      case Ci.nsIAccessibleRole.ROLE_STATICTEXT:
+          return FILTER_IGNORE;
+      case ROLE_STATICTEXT:
         {
           let parent = aAccessible.parent;
           // Ignore prefix static text in list items. They are typically bullets or numbers.
           if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
-              parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM)
-            return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+              parent.role == ROLE_LISTITEM)
+            return FILTER_IGNORE;
 
-          return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+          return FILTER_MATCH;
         }
+      case ROLE_GRAPHIC:
+        return TraversalRules._shouldSkipImage(aAccessible);
       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;
+        return FILTER_MATCH |
+          FILTER_IGNORE_SUBTREE;
       }
     }
   ),
 
   SimpleTouch: new BaseTraversalRule(
     gSimpleTraversalRoles,
     function Simple_match(aAccessible) {
-      return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
-        Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
+      return FILTER_MATCH |
+        FILTER_IGNORE_SUBTREE;
     }
   ),
 
   Anchor: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LINK],
+    [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;
+        return FILTER_IGNORE;
       } else {
-        return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
+        return 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]),
+    [ROLE_PUSHBUTTON,
+     ROLE_SPINBUTTON,
+     ROLE_TOGGLE_BUTTON,
+     ROLE_BUTTONDROPDOWN,
+     ROLE_BUTTONDROPDOWNGRID]),
 
   Combobox: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_COMBOBOX,
-     Ci.nsIAccessibleRole.ROLE_LISTBOX]),
+    [ROLE_COMBOBOX,
+     ROLE_LISTBOX]),
 
   Entry: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_ENTRY,
-     Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT]),
+    [ROLE_ENTRY,
+     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]),
+    [ROLE_PUSHBUTTON,
+     ROLE_SPINBUTTON,
+     ROLE_TOGGLE_BUTTON,
+     ROLE_BUTTONDROPDOWN,
+     ROLE_BUTTONDROPDOWNGRID,
+     ROLE_COMBOBOX,
+     ROLE_LISTBOX,
+     ROLE_ENTRY,
+     ROLE_PASSWORD_TEXT,
+     ROLE_PAGETAB,
+     ROLE_RADIOBUTTON,
+     ROLE_RADIO_MENU_ITEM,
+     ROLE_SLIDER,
+     ROLE_CHECKBUTTON,
+     ROLE_CHECK_MENU_ITEM]),
 
   Graphic: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_GRAPHIC]),
+    [ROLE_GRAPHIC],
+    function Graphic_match(aAccessible) {
+      return TraversalRules._shouldSkipImage(aAccessible);
+    }),
 
   Heading: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_HEADING]),
+    [ROLE_HEADING]),
 
   ListItem: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LISTITEM,
-     Ci.nsIAccessibleRole.ROLE_TERM]),
+    [ROLE_LISTITEM,
+     ROLE_TERM]),
 
   Link: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LINK],
+    [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;
+        return FILTER_MATCH;
       } else {
-        return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
+        return FILTER_IGNORE;
       }
     }),
 
   List: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_LIST,
-     Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST]),
+    [ROLE_LIST,
+     ROLE_DEFINITION_LIST]),
 
   PageTab: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_PAGETAB]),
+    [ROLE_PAGETAB]),
 
   RadioButton: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
-     Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM]),
+    [ROLE_RADIOBUTTON,
+     ROLE_RADIO_MENU_ITEM]),
 
   Separator: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_SEPARATOR]),
+    [ROLE_SEPARATOR]),
 
   Table: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_TABLE]),
+    [ROLE_TABLE]),
 
   Checkbox: new BaseTraversalRule(
-    [Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
-     Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM])
+    [ROLE_CHECKBUTTON,
+     ROLE_CHECK_MENU_ITEM]),
+
+  _shouldSkipImage: function _shouldSkipImage(aAccessible) {
+    if (gSkipEmptyImages.value && aAccessible.name === '') {
+      return FILTER_IGNORE;
+    }
+    return FILTER_MATCH;
+  }
 };
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -3,16 +3,22 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
+const EVENT_STATE_CHANGE = Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE;
+
+const ROLE_CELL = Ci.nsIAccessibleRole.ROLE_CELL;
+const ROLE_COLUMNHEADER = Ci.nsIAccessibleRole.ROLE_COLUMNHEADER;
+const ROLE_ROWHEADER = Ci.nsIAccessibleRole.ROLE_ROWHEADER;
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, 'Services',
   'resource://gre/modules/Services.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Rect',
   'resource://gre/modules/Geometry.jsm');
 
 this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache'];
 
@@ -66,16 +72,22 @@ this.Utils = {
   },
 
   get OS() {
     if (!this._OS)
       this._OS = Services.appinfo.OS;
     return this._OS;
   },
 
+  get widgetToolkit() {
+    if (!this._widgetToolkit)
+      this._widgetToolkit = Services.appinfo.widgetToolkit;
+    return this._widgetToolkit;
+  },
+
   get ScriptName() {
     if (!this._ScriptName)
       this._ScriptName =
         (Services.appinfo.processType == 2) ? 'AccessFuContent' : 'AccessFu';
     return this._ScriptName;
   },
 
   get AndroidSdkVersion() {
@@ -180,25 +192,28 @@ this.Utils = {
 
     let state = {};
     let extState = {};
     aAccessible.getState(state, extState);
     return [state.value, extState.value];
   },
 
   getAttributes: function getAttributes(aAccessible) {
-    let attributesEnum = aAccessible.attributes.enumerate();
     let attributes = {};
 
-    // Populate |attributes| object with |aAccessible|'s attribute key-value
-    // pairs.
-    while (attributesEnum.hasMoreElements()) {
-      let attribute = attributesEnum.getNext().QueryInterface(
-        Ci.nsIPropertyElement);
-      attributes[attribute.key] = attribute.value;
+    if (aAccessible && aAccessible.attributes) {
+      let attributesEnum = aAccessible.attributes.enumerate();
+
+      // Populate |attributes| object with |aAccessible|'s attribute key-value
+      // pairs.
+      while (attributesEnum.hasMoreElements()) {
+        let attribute = attributesEnum.getNext().QueryInterface(
+          Ci.nsIPropertyElement);
+        attributes[attribute.key] = attribute.value;
+      }
     }
 
     return attributes;
   },
 
   getVirtualCursor: function getVirtualCursor(aDocument) {
     let doc = (aDocument instanceof Ci.nsIAccessible) ? aDocument :
       this.AccRetrieval.getAccessibleFor(aDocument);
@@ -257,22 +272,37 @@ this.Logger = {
       this, [this.WARNING].concat(Array.prototype.slice.call(arguments)));
   },
 
   error: function error() {
     this.log.apply(
       this, [this.ERROR].concat(Array.prototype.slice.call(arguments)));
   },
 
-  logException: function logException(aException) {
+  logException: function logException(
+    aException, aErrorMessage = 'An exception has occured') {
     try {
-      let args = [aException.message];
-      args.push.apply(args, aException.stack ? ['\n', aException.stack] :
-        ['(' + aException.fileName + ':' + aException.lineNumber + ')']);
-      this.error.apply(this, args);
+      let stackMessage = '';
+      if (aException.stack) {
+        stackMessage = '  ' + aException.stack.replace(/\n/g, '\n  ');
+      } else if (aException.location) {
+        let frame = aException.location;
+        let stackLines = [];
+        while (frame && frame.lineNumber) {
+          stackLines.push(
+            '  ' + frame.name + '@' + frame.filename + ':' + frame.lineNumber);
+          frame = frame.caller;
+        }
+        stackMessage = stackLines.join('\n');
+      } else {
+        stackMessage = '(' + aException.fileName + ':' + aException.lineNumber + ')';
+      }
+      this.error(aErrorMessage + ':\n ' +
+                 aException.message + '\n' +
+                 stackMessage);
     } catch (x) {
       this.error(x);
     }
   },
 
   accessibleToString: function accessibleToString(aAccessible) {
     let str = '[ defunct ]';
     try {
@@ -281,17 +311,17 @@ this.Logger = {
     } catch (x) {
     }
 
     return str;
   },
 
   eventToString: function eventToString(aEvent) {
     let str = Utils.AccRetrieval.getStringEventType(aEvent.eventType);
-    if (aEvent.eventType == Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE) {
+    if (aEvent.eventType == EVENT_STATE_CHANGE) {
       let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
       let stateStrings = event.isExtraState ?
         Utils.AccRetrieval.getStringStates(0, event.state) :
         Utils.AccRetrieval.getStringStates(event.state, 0);
       str += ' (' + stateStrings.item(0) + ')';
     }
 
     return str;
@@ -339,93 +369,197 @@ PivotContext.prototype = {
   get accessible() {
     return this._accessible;
   },
 
   get oldAccessible() {
     return this._oldAccessible;
   },
 
+  /**
+   * Get a list of |aAccessible|'s ancestry up to the root.
+   * @param  {nsIAccessible} aAccessible.
+   * @return {Array} Ancestry list.
+   */
+  _getAncestry: function _getAncestry(aAccessible) {
+    let ancestry = [];
+    let parent = aAccessible;
+    while (parent && (parent = parent.parent)) {
+      ancestry.push(parent);
+    }
+    return ancestry.reverse();
+  },
+
+  /**
+   * A list of the old accessible's ancestry.
+   */
+  get oldAncestry() {
+    if (!this._oldAncestry) {
+      if (!this._oldAccessible) {
+        this._oldAncestry = [];
+      } else {
+        this._oldAncestry = this._getAncestry(this._oldAccessible);
+        this._oldAncestry.push(this._oldAccessible);
+      }
+    }
+    return this._oldAncestry;
+  },
+
+  /**
+   * A list of the current accessible's ancestry.
+   */
+  get currentAncestry() {
+    if (!this._currentAncestry) {
+      this._currentAncestry = this._getAncestry(this._accessible);
+    }
+    return this._currentAncestry;
+  },
+
   /*
    * This is a list of the accessible's ancestry up to the common ancestor
    * of the accessible and the old accessible. It is useful for giving the
    * user context as to where they are in the heirarchy.
    */
   get newAncestry() {
     if (!this._newAncestry) {
-      let newLineage = [];
-      let oldLineage = [];
-
-      let parent = this._accessible;
-      while (parent && (parent = parent.parent))
-        newLineage.push(parent);
-
-      parent = this._oldAccessible;
-      while (parent && (parent = parent.parent))
-        oldLineage.push(parent);
-
-      this._newAncestry = [];
-
-      while (true) {
-        let newAncestor = newLineage.pop();
-        let oldAncestor = oldLineage.pop();
-
-        if (newAncestor == undefined)
-          break;
-
-        if (newAncestor != oldAncestor)
-          this._newAncestry.push(newAncestor);
-      }
-
+      this._newAncestry = [currentAncestor for (
+        [index, currentAncestor] of Iterator(this.currentAncestry)) if (
+          currentAncestor !== this.oldAncestry[index])];
     }
-
     return this._newAncestry;
   },
 
   /*
    * Traverse the accessible's subtree in pre or post order.
    * It only includes the accessible's visible chidren.
+   * Note: needSubtree is a function argument that can be used to determine
+   * whether aAccessible's subtree is required.
    */
-  _traverse: function _traverse(aAccessible, preorder) {
-    let list = [];
+  _traverse: function _traverse(aAccessible, aPreorder, aStop) {
+    if (aStop && aStop(aAccessible)) {
+      return;
+    }
     let child = aAccessible.firstChild;
     while (child) {
       let state = {};
       child.getState(state, {});
       if (!(state.value & Ci.nsIAccessibleStates.STATE_INVISIBLE)) {
-        let traversed = _traverse(child, preorder);
-        // Prepend or append a child, based on traverse order.
-        traversed[preorder ? "unshift" : "push"](child);
-        list.push.apply(list, traversed);
+        if (aPreorder) {
+          yield child;
+          [yield node for (node of this._traverse(child, aPreorder, aStop))];
+        } else {
+          [yield node for (node of this._traverse(child, aPreorder, aStop))];
+          yield child;
+        }
       }
       child = child.nextSibling;
     }
-    return list;
   },
 
   /*
-   * This is a flattened list of the accessible's subtree in preorder.
+   * A subtree generator function, used to generate a flattened
+   * list of the accessible's subtree in pre or post order.
    * It only includes the accessible's visible chidren.
+   * @param {boolean} aPreorder A flag for traversal order. If true, traverse
+   * in preorder; if false, traverse in postorder.
+   * @param {function} aStop An optional function, indicating whether subtree
+   * traversal should stop.
    */
-  get subtreePreorder() {
-    if (!this._subtreePreOrder)
-      this._subtreePreOrder = this._traverse(this._accessible, true);
-
-    return this._subtreePreOrder;
+  subtreeGenerator: function subtreeGenerator(aPreorder, aStop) {
+    return this._traverse(this._accessible, aPreorder, aStop);
   },
 
-  /*
-   * This is a flattened list of the accessible's subtree in postorder.
-   * It only includes the accessible's visible chidren.
-   */
-  get subtreePostorder() {
-    if (!this._subtreePostOrder)
-      this._subtreePostOrder = this._traverse(this._accessible, false);
+  getCellInfo: function getCellInfo(aAccessible) {
+    if (!this._cells) {
+      this._cells = new WeakMap();
+    }
+
+    let domNode = aAccessible.DOMNode;
+    if (this._cells.has(domNode)) {
+      return this._cells.get(domNode);
+    }
+
+    let cellInfo = {};
+    let getAccessibleCell = function getAccessibleCell(aAccessible) {
+      if (!aAccessible) {
+        return null;
+      }
+      if ([ROLE_CELL, ROLE_COLUMNHEADER, ROLE_ROWHEADER].indexOf(
+        aAccessible.role) < 0) {
+          return null;
+      }
+      try {
+        return aAccessible.QueryInterface(Ci.nsIAccessibleTableCell);
+      } catch (x) {
+        Logger.logException(x);
+        return null;
+      }
+    };
+    let getHeaders = function getHeaders(aHeaderCells) {
+      let enumerator = aHeaderCells.enumerate();
+      while (enumerator.hasMoreElements()) {
+        yield enumerator.getNext().QueryInterface(Ci.nsIAccessible).name;
+      }
+    };
+
+    cellInfo.current = getAccessibleCell(aAccessible);
+
+    if (!cellInfo.current) {
+      Logger.warning(aAccessible,
+        'does not support nsIAccessibleTableCell interface.');
+      this._cells.set(domNode, null);
+      return null;
+    }
 
-    return this._subtreePostOrder;
+    let table = cellInfo.current.table;
+    if (table.isProbablyForLayout()) {
+      this._cells.set(domNode, null);
+      return null;
+    }
+
+    cellInfo.previous = null;
+    let oldAncestry = this.oldAncestry.reverse();
+    let ancestor = oldAncestry.shift();
+    while (!cellInfo.previous && ancestor) {
+      let cell = getAccessibleCell(ancestor);
+      if (cell && cell.table === table) {
+        cellInfo.previous = cell;
+      }
+      ancestor = oldAncestry.shift();
+    }
+
+    if (cellInfo.previous) {
+      cellInfo.rowChanged = cellInfo.current.rowIndex !==
+        cellInfo.previous.rowIndex;
+      cellInfo.columnChanged = cellInfo.current.columnIndex !==
+        cellInfo.previous.columnIndex;
+    } else {
+      cellInfo.rowChanged = true;
+      cellInfo.columnChanged = true;
+    }
+
+    cellInfo.rowExtent = cellInfo.current.rowExtent;
+    cellInfo.columnExtent = cellInfo.current.columnExtent;
+    cellInfo.columnIndex = cellInfo.current.columnIndex;
+    cellInfo.rowIndex = cellInfo.current.rowIndex;
+
+    cellInfo.columnHeaders = [];
+    if (cellInfo.columnChanged && cellInfo.current.role !==
+      ROLE_COLUMNHEADER) {
+      cellInfo.columnHeaders = [headers for (headers of getHeaders(
+        cellInfo.current.columnHeaderCells))];
+    }
+    cellInfo.rowHeaders = [];
+    if (cellInfo.rowChanged && cellInfo.current.role === ROLE_CELL) {
+      cellInfo.rowHeaders = [headers for (headers of getHeaders(
+        cellInfo.current.rowHeaderCells))];
+    }
+
+    this._cells.set(domNode, cellInfo);
+    return cellInfo;
   },
 
   get bounds() {
     if (!this._bounds) {
       let objX = {}, objY = {}, objW = {}, objH = {};
 
       this._accessible.getBounds(objX, objY, objW, objH);
 
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -1,26 +1,30 @@
 /* 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/. */
 
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
+const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
+
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
   'resource://gre/modules/accessibility/Presentation.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
   'resource://gre/modules/accessibility/TraversalRules.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',
   'resource://gre/modules/accessibility/EventManager.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'ObjectWrapper',
+  'resource://gre/modules/ObjectWrapper.jsm');
 
 Logger.debug('content-script.js');
 
 let eventManager = null;
 
 function virtualCursorControl(aMessage) {
   if (Logger.logLevel >= Logger.DEBUG)
     Logger.debug(aMessage.name, JSON.stringify(aMessage.json));
@@ -86,24 +90,24 @@ function virtualCursorControl(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);
+    Logger.logException(x, 'Failed to move virtual cursor');
   }
 }
 
 function forwardMessage(aVirtualCursor, aMessage) {
   try {
     let acc = aVirtualCursor.position;
-    if (acc && acc.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
+    if (acc && acc.role == ROLE_INTERNAL_FRAME) {
       let mm = Utils.getMessageManager(acc.DOMNode);
       mm.addMessageListener(aMessage.name, virtualCursorControl);
       aMessage.json.origin = 'parent';
       if (Utils.isContentProcess) {
         // 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;
@@ -165,28 +169,95 @@ function activateContextMenu(aMessage) {
     sendAsyncMessage('AccessFu:ActivateContextMenu', {x: x, y: y});
   }
 
   let vc = Utils.getVirtualCursor(content.document);
   if (!forwardMessage(vc, aMessage))
     sendContextMenuCoordinates(vc.position);
 }
 
+function moveCaret(aMessage) {
+  const MOVEMENT_GRANULARITY_CHARACTER = 1;
+  const MOVEMENT_GRANULARITY_WORD = 2;
+  const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
+
+  let direction = aMessage.json.direction;
+  let granularity = aMessage.json.granularity;
+  let accessible = Utils.getVirtualCursor(content.document).position;
+  let accText = accessible.QueryInterface(Ci.nsIAccessibleText);
+  let oldOffset = accText.caretOffset;
+  let text = accText.getText(0, accText.characterCount);
+
+  let start = {}, end = {};
+  if (direction === 'Previous' && !aMessage.json.atStart) {
+    switch (granularity) {
+      case MOVEMENT_GRANULARITY_CHARACTER:
+        accText.caretOffset--;
+        break;
+      case MOVEMENT_GRANULARITY_WORD:
+        accText.getTextBeforeOffset(accText.caretOffset,
+                                    Ci.nsIAccessibleText.BOUNDARY_WORD_START, start, end);
+        accText.caretOffset = end.value === accText.caretOffset ? start.value : end.value;
+        break;
+      case MOVEMENT_GRANULARITY_PARAGRAPH:
+        let startOfParagraph = text.lastIndexOf('\n', accText.caretOffset - 1);
+        accText.caretOffset = startOfParagraph !== -1 ? startOfParagraph : 0;
+        break;
+    }
+  } else if (direction === 'Next' && !aMessage.json.atEnd) {
+    switch (granularity) {
+      case MOVEMENT_GRANULARITY_CHARACTER:
+        accText.caretOffset++;
+        break;
+      case MOVEMENT_GRANULARITY_WORD:
+        accText.getTextAtOffset(accText.caretOffset,
+                                Ci.nsIAccessibleText.BOUNDARY_WORD_END, start, end);
+        accText.caretOffset = end.value;
+        break;
+      case MOVEMENT_GRANULARITY_PARAGRAPH:
+        accText.caretOffset = text.indexOf('\n', accText.caretOffset + 1);
+        break;
+    }
+  }
+
+  let newOffset = accText.caretOffset;
+  if (oldOffset !== newOffset) {
+    let msg = Presentation.textSelectionChanged(text, newOffset, newOffset,
+                                                oldOffset, oldOffset);
+    sendAsyncMessage('AccessFu:Present', msg);
+  }
+}
+
 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;
 
+      // This is inspired by IndieUI events. Once they are
+      // implemented, it should be easy to transition to them.
+      // https://dvcs.w3.org/hg/IndieUI/raw-file/tip/src/indie-ui-events.html#scrollrequest
+      let uiactions = elem.getAttribute ? elem.getAttribute('uiactions') : '';
+      if (uiactions && uiactions.split(' ').indexOf('scroll') >= 0) {
+        let evt = elem.ownerDocument.createEvent('CustomEvent');
+        let details = horiz ? { deltaX: page * elem.clientWidth } :
+          { deltaY: page * elem.clientHeight };
+        evt.initCustomEvent(
+          'scrollrequest', true, true,
+          ObjectWrapper.wrap(details, elem.ownerDocument.defaultView));
+        if (!elem.dispatchEvent(evt))
+          return;
+      }
+
       // 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;
@@ -197,35 +268,16 @@ function scroll(aMessage) {
       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))) {
@@ -259,29 +311,31 @@ addMessageListener(
     Logger.debug('AccessFu:Start');
     if (m.json.buildApp)
       Utils.MozBuildApp = m.json.buildApp;
 
     addMessageListener('AccessFu:VirtualCursor', virtualCursorControl);
     addMessageListener('AccessFu:Activate', activateCurrent);
     addMessageListener('AccessFu:ContextMenu', activateContextMenu);
     addMessageListener('AccessFu:Scroll', scroll);
+    addMessageListener('AccessFu:MoveCaret', moveCaret);
 
     if (!eventManager) {
       eventManager = new EventManager(this);
     }
     eventManager.start();
   });
 
 addMessageListener(
   'AccessFu:Stop',
   function(m) {
     Logger.debug('AccessFu:Stop');
 
     removeMessageListener('AccessFu:VirtualCursor', virtualCursorControl);
     removeMessageListener('AccessFu:Activate', activateCurrent);
     removeMessageListener('AccessFu:ContextMenu', activateContextMenu);
     removeMessageListener('AccessFu:Scroll', scroll);
+    removeMessageListener('AccessFu:MoveCaret', moveCaret);
 
     eventManager.stop();
   });
 
 sendAsyncMessage('AccessFu:Ready');
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -4,21 +4,20 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
-CMMSRCS = \
+DISABLED_CMMSRCS = \
           AccessibleWrap.mm \
           DocAccessibleWrap.mm \
           mozAccessible.mm \
           mozDocAccessible.mm \
           mozActionElements.mm \
           mozTextAccessible.mm \
           mozHTMLAccessible.mm \
           MacUtils.mm \
--- a/accessible/src/mac/moz.build
+++ b/accessible/src/mac/moz.build
@@ -10,8 +10,22 @@ EXPORTS += [
     'mozAccessibleProtocol.h',
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'HyperTextAccessibleWrap.h',
 ]
 
+LIBRARY_NAME = 'accessibility_toolkit_s'
+
+CMMSRCS += [
+    'AccessibleWrap.mm',
+    'DocAccessibleWrap.mm',
+    'MacUtils.mm',
+    'Platform.mm',
+    'RootAccessibleWrap.mm',
+    'mozAccessible.mm',
+    'mozActionElements.mm',
+    'mozDocAccessible.mm',
+    'mozHTMLAccessible.mm',
+    'mozTextAccessible.mm',
+]
--- a/accessible/src/moz.build
+++ b/accessible/src/moz.build
@@ -1,17 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
-if toolkit == 'gtk2':
+if CONFIG['MOZ_ENABLE_GTK']:
     DIRS += ['atk']
 elif toolkit == 'windows':
     DIRS += ['windows']
 elif toolkit == 'cocoa':
     DIRS += ['mac']
 else:
     DIRS += ['other']
 
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -4,17 +4,16 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/src/other/moz.build
+++ b/accessible/src/other/moz.build
@@ -11,8 +11,10 @@ EXPORTS.mozilla.a11y += [
     'HyperTextAccessibleWrap.h',
 ]
 
 CPP_SOURCES += [
     'AccessibleWrap.cpp',
     'Platform.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_toolkit_s'
+
--- a/accessible/src/windows/ia2/ia2AccessibleAction.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleAction.cpp
@@ -14,16 +14,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleAction == iid) {
     *ppv = static_cast<IAccessibleAction*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -68,16 +71,19 @@ ia2AccessibleAction::doAction(long aActi
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aDescription)
+    return E_INVALIDARG;
+
   *aDescription = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString description;
   uint8_t index = static_cast<uint8_t>(aActionIndex);
@@ -145,16 +151,19 @@ ia2AccessibleAction::get_keyBinding(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aName)
+    return E_INVALIDARG;
+
   *aName = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
   uint8_t index = static_cast<uint8_t>(aActionIndex);
@@ -171,13 +180,16 @@ ia2AccessibleAction::get_name(long aActi
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aLocalizedName)
+    return E_INVALIDARG;
+
   *aLocalizedName = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
--- a/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
@@ -17,16 +17,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleComponent::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleComponent == iid) {
     *ppv = static_cast<IAccessibleComponent*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -35,16 +38,19 @@ ia2AccessibleComponent::QueryInterface(R
 
 // IAccessibleComponent
 
 STDMETHODIMP
 ia2AccessibleComponent::get_locationInParent(long* aX, long* aY)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aX || !aY)
+    return E_INVALIDARG;
+
   *aX = 0;
   *aY = 0;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   // If the object is not on any screen the returned position is (0,0).
@@ -82,16 +88,21 @@ ia2AccessibleComponent::get_locationInPa
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleComponent::get_foreground(IA2Color* aForeground)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aForeground)
+    return E_INVALIDARG;
+
+  *aForeground = 0;
+
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsIFrame* frame = acc->GetFrame();
   if (frame)
     *aForeground = frame->StyleColor()->mColor;
 
@@ -100,16 +111,21 @@ ia2AccessibleComponent::get_foreground(I
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleComponent::get_background(IA2Color* aBackground)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aBackground)
+    return E_INVALIDARG;
+
+  *aBackground = 0;
+
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsIFrame* frame = acc->GetFrame();
   if (frame)
     *aBackground = frame->StyleBackground()->mBackgroundColor;
 
--- a/accessible/src/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -14,16 +14,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleHyperlink == iid) {
     if (!static_cast<AccessibleWrap*>(this)->IsLink())
       return E_NOINTERFACE;
 
     *ppv = static_cast<IAccessibleHyperlink*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
@@ -35,16 +38,19 @@ ia2AccessibleHyperlink::QueryInterface(R
 
 // IAccessibleHyperlink
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAnchor)
+    return E_INVALIDARG;
+
   VariantInit(aAnchor);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
     return E_INVALIDARG;
@@ -70,16 +76,19 @@ ia2AccessibleHyperlink::get_anchor(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAnchorTarget)
+    return E_INVALIDARG;
+
   VariantInit(aAnchorTarget);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
     return E_INVALIDARG;
@@ -113,16 +122,19 @@ ia2AccessibleHyperlink::get_anchorTarget
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_startIndex(long* aIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIndex)
+    return E_INVALIDARG;
+
   *aIndex = 0;
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
@@ -133,16 +145,19 @@ ia2AccessibleHyperlink::get_startIndex(l
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_endIndex(long* aIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIndex)
+    return E_INVALIDARG;
+
   *aIndex = 0;
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
@@ -153,16 +168,19 @@ ia2AccessibleHyperlink::get_endIndex(lon
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHyperlink::get_valid(boolean* aValid)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aValid)
+    return E_INVALIDARG;
+
   *aValid = false;
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
--- a/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
@@ -16,16 +16,19 @@ using namespace mozilla::a11y;
 
 // IAccessibleHypertext
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_nHyperlinks(long* aHyperlinkCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aHyperlinkCount)
+    return E_INVALIDARG;
+
   *aHyperlinkCount = 0;
 
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkCount = hyperText->GetLinkCount();
   return S_OK;
@@ -34,16 +37,19 @@ ia2AccessibleHypertext::get_nHyperlinks(
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
                                       IAccessibleHyperlink** aHyperlink)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aHyperlink)
+    return E_INVALIDARG;
+
   *aHyperlink = nullptr;
 
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
   if (!hyperLink)
@@ -57,16 +63,19 @@ ia2AccessibleHypertext::get_hyperlink(lo
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aHyperlinkIndex)
+    return E_INVALIDARG;
+
   *aHyperlinkIndex = 0;
 
   HyperTextAccessibleWrap* hyperAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkIndex = hyperAcc->GetLinkIndexAtOffset(aCharIndex);
   return S_OK;
--- a/accessible/src/windows/ia2/ia2AccessibleImage.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleImage.cpp
@@ -18,16 +18,19 @@
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleImage::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleImage == iid) {
     *ppv = static_cast<IAccessibleImage*>(this);
     (static_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -36,16 +39,19 @@ ia2AccessibleImage::QueryInterface(REFII
 
 // IAccessibleImage
 
 STDMETHODIMP
 ia2AccessibleImage::get_description(BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aDescription)
+    return E_INVALIDARG;
+
   *aDescription = nullptr;
 
   ImageAccessibleWrap* acc = static_cast<ImageAccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString description;
   nsresult rv = acc->GetName(description);
@@ -63,16 +69,19 @@ ia2AccessibleImage::get_description(BSTR
 
 STDMETHODIMP
 ia2AccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
                                       long* aX,
                                       long* aY)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aX || !aY)
+    return E_INVALIDARG;
+
   *aX = 0;
   *aY = 0;
 
   ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
   if (imageAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
@@ -91,16 +100,19 @@ ia2AccessibleImage::get_imagePosition(en
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleImage::get_imageSize(long* aHeight, long* aWidth)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aHeight || !aWidth)
+    return E_INVALIDARG;
+
   *aHeight = 0;
   *aWidth = 0;
 
   ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
   if (imageAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   int32_t width = 0, height = 0;
--- a/accessible/src/windows/ia2/ia2AccessibleTable.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleTable.cpp
@@ -21,16 +21,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleTable::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleTable == iid) {
     statistics::IAccessibleTableUsed();
     *ppv = static_cast<IAccessibleTable*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
@@ -54,16 +57,19 @@ ia2AccessibleTable::get_accessibleAt(lon
   return get_cellAt(aRowIdx, aColIdx, aAccessible);
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_caption(IUnknown** aAccessible)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAccessible)
+    return E_INVALIDARG;
+
   *aAccessible = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   AccessibleWrap* caption = static_cast<AccessibleWrap*>(mTable->Caption());
   if (!caption)
     return S_FALSE;
 
@@ -74,16 +80,19 @@ ia2AccessibleTable::get_caption(IUnknown
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
                                    long* aChildIdx)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aChildIdx)
+    return E_INVALIDARG;
+
   *aChildIdx = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || aColIdx < 0 ||
       static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
       static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
@@ -94,16 +103,19 @@ ia2AccessibleTable::get_childIndex(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aDescription)
+    return E_INVALIDARG;
+
   *aDescription = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
 
   nsAutoString descr;
@@ -118,16 +130,19 @@ ia2AccessibleTable::get_columnDescriptio
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
                                       long* aSpan)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aSpan)
+    return E_INVALIDARG;
+
   *aSpan = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || aColIdx < 0 ||
       static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
       static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
@@ -139,28 +154,34 @@ ia2AccessibleTable::get_columnExtentAt(l
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
                                     long* aStartingRowIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAccessibleTable || !aStartingRowIndex)
+    return E_INVALIDARG;
+
   *aAccessibleTable = nullptr;
   *aStartingRowIndex = -1;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aColIdx)
+    return E_INVALIDARG;
+
   *aColIdx = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aCellIdx < 0 ||
       static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
     return E_INVALIDARG;
 
@@ -170,31 +191,37 @@ ia2AccessibleTable::get_columnIndex(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nColumns(long* aColCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aColCount)
+    return E_INVALIDARG;
+
   *aColCount = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   *aColCount = mTable->ColCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nRows(long* aRowCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowCount)
+    return E_INVALIDARG;
+
   *aRowCount = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   *aRowCount = mTable->RowCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -206,47 +233,56 @@ ia2AccessibleTable::get_nSelectedChildre
   return get_nSelectedCells(aChildCount);
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aColCount)
+    return E_INVALIDARG;
+
   *aColCount = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   *aColCount = mTable->SelectedColCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowCount)
+    return E_INVALIDARG;
+
   *aRowCount = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   *aRowCount = mTable->SelectedRowCount();
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aDescription)
+    return E_INVALIDARG;
+
   *aDescription = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
     return E_INVALIDARG;
 
   nsAutoString descr;
@@ -260,16 +296,19 @@ ia2AccessibleTable::get_rowDescription(l
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aSpan)
+    return E_INVALIDARG;
+
   *aSpan = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || aColIdx < 0 ||
       static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
       static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
@@ -281,28 +320,34 @@ ia2AccessibleTable::get_rowExtentAt(long
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
                                   long* aStartingColumnIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAccessibleTable || !aStartingColumnIndex)
+    return E_INVALIDARG;
+
   *aAccessibleTable = nullptr;
   *aStartingColumnIndex = -1;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowIdx)
+    return E_INVALIDARG;
+
   *aRowIdx = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aCellIdx < 0 ||
       static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
     return E_INVALIDARG;
 
@@ -313,16 +358,19 @@ ia2AccessibleTable::get_rowIndex(long aC
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
                                          long* aNChildren)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aChildren || !aNChildren)
+    return E_INVALIDARG;
+
   *aChildren = nullptr;
   *aNChildren = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> cellIndices;
   mTable->SelectedCellIndices(&cellIndices);
 
@@ -361,32 +409,38 @@ ia2AccessibleTable::get_selectedRows(lon
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_summary(IUnknown** aAccessible)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAccessible)
+    return E_INVALIDARG;
+
   // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
   // link an accessible object to specify a summary. There is closes method
   // in nsIAccessibleTable::summary to get a summary as a string which is not
   // mapped directly to IAccessible2.
 
   *aAccessible = nullptr;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIsSelected)
+    return E_INVALIDARG;
+
   *aIsSelected = false;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
 
   *aIsSelected = mTable->IsColSelected(aColIdx);
@@ -395,16 +449,19 @@ ia2AccessibleTable::get_isColumnSelected
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIsSelected)
+    return E_INVALIDARG;
+
   *aIsSelected = false;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
     return E_INVALIDARG;
 
   *aIsSelected = mTable->IsRowSelected(aRowIdx);
@@ -414,16 +471,19 @@ ia2AccessibleTable::get_isRowSelected(lo
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
                                    boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIsSelected)
+    return E_INVALIDARG;
+
   *aIsSelected = false;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || aColIdx < 0 ||
       static_cast<uint32_t>(aColIdx) >= mTable->ColCount() ||
       static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
     return E_INVALIDARG;
@@ -506,16 +566,19 @@ STDMETHODIMP
 ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
                                                 long* aColIdx,
                                                 long* aRowExtents,
                                                 long* aColExtents,
                                                 boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
+    return E_INVALIDARG;
+
   *aRowIdx = 0;
   *aColIdx = 0;
   *aRowExtents = 0;
   *aColExtents = 0;
   *aIsSelected = false;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
@@ -545,16 +608,19 @@ ia2AccessibleTable::get_modelChange(IA2T
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleTable2
 
 STDMETHODIMP
 ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCell)
+    return E_INVALIDARG;
+
   *aCell = nullptr;
 
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   AccessibleWrap* cell =
     static_cast<AccessibleWrap*>(mTable->CellAt(aRowIdx, aColIdx));
   if (!cell)
@@ -566,31 +632,37 @@ ia2AccessibleTable::get_cellAt(long aRow
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCellCount)
+    return E_INVALIDARG;
+
   *aCellCount = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   *aCellCount = mTable->SelectedCellCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCells || !aNSelectedCells)
+    return E_INVALIDARG;
+
   *aCells = nullptr;
   *aNSelectedCells = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 30> cells;
   mTable->SelectedCells(&cells);
   if (cells.IsEmpty())
@@ -614,16 +686,19 @@ ia2AccessibleTable::get_selectedCells(IU
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aColumns || !aNColumns)
+    return E_INVALIDARG;
+
   *aColumns = nullptr;
   *aNColumns = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> colIndices;
   mTable->SelectedColIndices(&colIndices);
 
@@ -641,16 +716,19 @@ ia2AccessibleTable::get_selectedColumns(
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRows || !aNRows)
+    return E_INVALIDARG;
+
   *aRows = nullptr;
   *aNRows = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> rowIndices;
   mTable->SelectedRowIndices(&rowIndices);
 
--- a/accessible/src/windows/ia2/ia2AccessibleTableCell.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleTableCell.cpp
@@ -21,16 +21,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleTableCell::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleTableCell == iid) {
     *ppv = static_cast<IAccessibleTableCell*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -40,16 +43,19 @@ ia2AccessibleTableCell::QueryInterface(R
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleTableCell
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_table(IUnknown** aTable)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aTable)
+    return E_INVALIDARG;
+
   *aTable = nullptr;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   TableAccessible* table = mTableCell->Table();
   if (!table)
     return E_FAIL;
 
@@ -61,16 +67,19 @@ ia2AccessibleTableCell::get_table(IUnkno
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnExtent(long* aSpan)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aSpan)
+    return E_INVALIDARG;
+
   *aSpan = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aSpan = mTableCell->ColExtent();
 
   return S_OK;
 
@@ -78,16 +87,19 @@ ia2AccessibleTableCell::get_columnExtent
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
                                               long* aNColumnHeaderCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCellAccessibles || !aNColumnHeaderCells)
+    return E_INVALIDARG;
+
   *aCellAccessibles = nullptr;
   *aNColumnHeaderCells = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 10> cells;
   mTableCell->ColHeaderCells(&cells);
 
@@ -110,47 +122,56 @@ ia2AccessibleTableCell::get_columnHeader
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnIndex(long* aColIdx)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aColIdx)
+    return E_INVALIDARG;
+
   *aColIdx = -1;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aColIdx = mTableCell->ColIdx();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowExtent(long* aSpan)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aSpan)
+    return E_INVALIDARG;
+
   *aSpan = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aSpan = mTableCell->RowExtent();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
                                            long* aNRowHeaderCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCellAccessibles || !aNRowHeaderCells)
+    return E_INVALIDARG;
+
   *aCellAccessibles = nullptr;
   *aNRowHeaderCells = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 10> cells;
   mTableCell->RowHeaderCells(&cells);
 
@@ -172,16 +193,19 @@ ia2AccessibleTableCell::get_rowHeaderCel
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowIndex(long* aRowIdx)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowIdx)
+    return E_INVALIDARG;
+
   *aRowIdx = -1;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aRowIdx = mTableCell->RowIdx();
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -190,16 +214,19 @@ ia2AccessibleTableCell::get_rowIndex(lon
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowColumnExtents(long* aRowIdx, long* aColIdx,
                                              long* aRowExtents,
                                              long* aColExtents,
                                              boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
+    return E_INVALIDARG;
+
   *aRowIdx = *aColIdx = *aRowExtents = *aColExtents = 0;
   *aIsSelected = false;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aRowIdx = mTableCell->RowIdx();
   *aColIdx = mTableCell->ColIdx();
   *aRowExtents = mTableCell->RowExtent();
@@ -211,16 +238,19 @@ ia2AccessibleTableCell::get_rowColumnExt
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_isSelected(boolean* aIsSelected)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aIsSelected)
+    return E_INVALIDARG;
+
   *aIsSelected = false;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   *aIsSelected = mTableCell->Selected();
   return S_OK;
 
   A11Y_TRYBLOCK_END
--- a/accessible/src/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleText.cpp
@@ -71,16 +71,19 @@ ia2AccessibleText::get_attributes(long a
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_caretOffset(long *aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aOffset)
+    return E_INVALIDARG;
+
   *aOffset = -1;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   int32_t offset = 0;
   nsresult rv = textAcc->GetCaretOffset(&offset);
@@ -96,16 +99,19 @@ ia2AccessibleText::get_caretOffset(long 
 STDMETHODIMP
 ia2AccessibleText::get_characterExtents(long aOffset,
                                         enum IA2CoordinateType aCoordType,
                                         long *aX, long *aY,
                                         long *aWidth, long *aHeight)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aX || !aY || !aWidth || !aHeight)
+    return E_INVALIDARG;
+
   *aX = 0;
   *aY = 0;
   *aWidth = 0;
   *aHeight = 0;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
@@ -129,16 +135,19 @@ ia2AccessibleText::get_characterExtents(
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_nSelections(long *aNSelections)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aNSelections)
+    return E_INVALIDARG;
+
   *aNSelections = 0;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   int32_t selCount = 0;
   nsresult rv = textAcc->GetSelectionCount(&selCount);
@@ -153,16 +162,19 @@ ia2AccessibleText::get_nSelections(long 
 
 STDMETHODIMP
 ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
                                      enum IA2CoordinateType aCoordType,
                                      long *aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aOffset)
+    return E_INVALIDARG;
+
   *aOffset = 0;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
     nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
@@ -180,16 +192,19 @@ ia2AccessibleText::get_offsetAtPoint(lon
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
                                  long *aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aStartOffset || !aEndOffset)
+    return E_INVALIDARG;
+
   *aStartOffset = 0;
   *aEndOffset = 0;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   int32_t startOffset = 0, endOffset = 0;
@@ -205,16 +220,19 @@ ia2AccessibleText::get_selection(long aS
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aText)
+    return E_INVALIDARG;
+
   *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString text;
   nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
@@ -233,16 +251,19 @@ ia2AccessibleText::get_text(long aStartO
 STDMETHODIMP
 ia2AccessibleText::get_textBeforeOffset(long aOffset,
                                         enum IA2TextBoundaryType aBoundaryType,
                                         long *aStartOffset, long *aEndOffset,
                                         BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aStartOffset || !aEndOffset || !aText)
+    return E_INVALIDARG;
+
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -280,16 +301,19 @@ ia2AccessibleText::get_textBeforeOffset(
 STDMETHODIMP
 ia2AccessibleText::get_textAfterOffset(long aOffset,
                                        enum IA2TextBoundaryType aBoundaryType,
                                        long *aStartOffset, long *aEndOffset,
                                        BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aStartOffset || !aEndOffset || !aText)
+    return E_INVALIDARG;
+
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -327,16 +351,19 @@ ia2AccessibleText::get_textAfterOffset(l
 STDMETHODIMP
 ia2AccessibleText::get_textAtOffset(long aOffset,
                                     enum IA2TextBoundaryType aBoundaryType,
                                     long *aStartOffset, long *aEndOffset,
                                     BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aStartOffset || !aEndOffset || !aText)
+    return E_INVALIDARG;
+
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -418,16 +445,19 @@ ia2AccessibleText::setSelection(long aSe
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_nCharacters(long *aNCharacters)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aNCharacters)
+    return E_INVALIDARG;
+
   *aNCharacters = 0;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aNCharacters  = textAcc->CharacterCount();
   return S_OK;
@@ -494,16 +524,19 @@ ia2AccessibleText::get_oldText(IA2TextSe
 }
 
 // ia2AccessibleText
 
 HRESULT
 ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
                                    IA2TextSegment *aText)
 {
+  if (!aText)
+    return E_INVALIDARG;
+
   uint32_t startOffset = 0, endOffset = 0;
   nsAutoString text;
 
   nsresult rv = GetModifiedText(aGetInsertedText, text,
                                 &startOffset, &endOffset);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
--- a/accessible/src/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleValue.cpp
@@ -15,16 +15,19 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleValue::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleValue == iid) {
     AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
     if (valueAcc->HasNumericValue()) {
       *ppv = static_cast<IAccessibleValue*>(this);
       valueAcc->AddRef();
       return S_OK;
@@ -38,16 +41,19 @@ ia2AccessibleValue::QueryInterface(REFII
 
 // IAccessibleValue
 
 STDMETHODIMP
 ia2AccessibleValue::get_currentValue(VARIANT* aCurrentValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCurrentValue)
+    return E_INVALIDARG;
+
   VariantInit(aCurrentValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   double currentValue = 0;
   nsresult rv = valueAcc->GetCurrentValue(&currentValue);
@@ -79,16 +85,19 @@ ia2AccessibleValue::setCurrentValue(VARI
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aMaximumValue)
+    return E_INVALIDARG;
+
   VariantInit(aMaximumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   double maximumValue = 0;
   nsresult rv = valueAcc->GetMaximumValue(&maximumValue);
@@ -102,16 +111,19 @@ ia2AccessibleValue::get_maximumValue(VAR
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_minimumValue(VARIANT* aMinimumValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aMinimumValue)
+    return E_INVALIDARG;
+
   VariantInit(aMinimumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   double minimumValue = 0;
   nsresult rv = valueAcc->GetMinimumValue(&minimumValue);
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/AccessibleWrap.cpp
@@ -73,16 +73,19 @@ NS_IMPL_ISUPPORTS_INHERITED0(AccessibleW
 //-----------------------------------------------------
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid)
     *ppv = static_cast<IAccessible*>(this);
   else if (IID_IEnumVARIANT == iid) {
     // Don't support this interface for leaf elements.
     if (!HasChildren() || nsAccUtils::MustPrune(this))
       return E_NOINTERFACE;
@@ -130,16 +133,19 @@ AccessibleWrap::QueryInterface(REFIID ii
 // IAccessible methods
 //-----------------------------------------------------
 
 STDMETHODIMP
 AccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!ppdispParent)
+    return E_INVALIDARG;
+
   *ppdispParent = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   DocAccessible* doc = AsDoc();
   if (doc) {
     // Return window system accessible object for root document and tab document
@@ -190,16 +196,19 @@ AccessibleWrap::get_accChildCount( long 
 
 STDMETHODIMP
 AccessibleWrap::get_accChild(
       /* [in] */ VARIANT varChild,
       /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!ppdispChild)
+    return E_INVALIDARG;
+
   *ppdispChild = nullptr;
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   // IAccessible::accChild is used to return this accessible or child accessible
   // at the given index or to get an accessible by child ID in the case of
   // document accessible (it's handled by overriden GetXPAccessibleFor method
   // on the document accessible). The getting an accessible by child ID is used
@@ -219,16 +228,19 @@ AccessibleWrap::get_accChild(
 
 STDMETHODIMP
 AccessibleWrap::get_accName(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszName)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszName)
+    return E_INVALIDARG;
+
   *pszName = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
@@ -256,16 +268,19 @@ AccessibleWrap::get_accName(
 
 STDMETHODIMP
 AccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszValue)
+    return E_INVALIDARG;
+
   *pszValue = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
@@ -294,16 +309,19 @@ AccessibleWrap::get_accValue(
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accDescription(VARIANT varChild,
                                    BSTR __RPC_FAR *pszDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszDescription)
+    return E_INVALIDARG;
+
   *pszDescription = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
@@ -323,16 +341,19 @@ AccessibleWrap::get_accDescription(VARIA
 
 STDMETHODIMP
 AccessibleWrap::get_accRole(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pvarRole)
+    return E_INVALIDARG;
+
   VariantInit(pvarRole);
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
@@ -352,17 +373,17 @@ AccessibleWrap::get_accRole(
              _msaaRole, ia2Role, nameRule) \
   case roles::_geckoRole: \
     msaaRole = _msaaRole; \
     break;
 
   switch (geckoRole) {
 #include "RoleMap.h"
     default:
-      MOZ_NOT_REACHED("Unknown role.");
+      MOZ_CRASH("Unknown role.");
   };
 
 #undef ROLE
 
   // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call the MSAA role
   // a ROLE_OUTLINEITEM for consistency and compatibility.
   // We need this because ARIA has a role of "row" for both grid and treegrid
   if (geckoRole == roles::ROW) {
@@ -418,16 +439,19 @@ AccessibleWrap::get_accRole(
 
 STDMETHODIMP
 AccessibleWrap::get_accState(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarState)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pvarState)
+    return E_INVALIDARG;
+
   VariantInit(pvarState);
   pvarState->vt = VT_I4;
   pvarState->lVal = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
@@ -456,30 +480,36 @@ AccessibleWrap::get_accState(
 
 STDMETHODIMP
 AccessibleWrap::get_accHelp(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszHelp)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszHelp)
+    return E_INVALIDARG;
+
   *pszHelp = nullptr;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accHelpTopic(
       /* [out] */ BSTR __RPC_FAR *pszHelpFile,
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ long __RPC_FAR *pidTopic)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszHelpFile || !pidTopic)
+    return E_INVALIDARG;
+
   *pszHelpFile = nullptr;
   *pidTopic = 0;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -518,27 +548,30 @@ AccessibleWrap::get_accKeyboardShortcut(
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accFocus(
       /* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pvarChild)
+    return E_INVALIDARG;
+
+  VariantInit(pvarChild);
+
   // VT_EMPTY:    None. This object does not have the keyboard focus itself
   //              and does not contain a child that has the keyboard focus.
   // VT_I4:       lVal is CHILDID_SELF. The object itself has the keyboard focus.
   // VT_I4:       lVal contains the child ID of the child element with the keyboard focus.
   // VT_DISPATCH: pdispVal member is the address of the IDispatch interface
   //              for the child object with the keyboard focus.
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  VariantInit(pvarChild);
-
   // Return the current IAccessible child that has focus
   Accessible* focusedAccessible = FocusedChild();
   if (focusedAccessible == this) {
     pvarChild->vt = VT_I4;
     pvarChild->lVal = CHILDID_SELF;
   }
   else if (focusedAccessible) {
     pvarChild->vt = VT_DISPATCH;
@@ -687,16 +720,19 @@ AccessibleEnumerator::Skip(unsigned long
   *  - there are no selected children for this object
   *  - the object is not the type that can have children selected
   */
 STDMETHODIMP
 AccessibleWrap::get_accSelection(VARIANT __RPC_FAR *pvarChildren)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pvarChildren)
+    return E_INVALIDARG;
+
   VariantInit(pvarChildren);
   pvarChildren->vt = VT_EMPTY;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (IsSelect()) {
     nsCOMPtr<nsIArray> selectedItems = SelectedItems();
@@ -719,16 +755,19 @@ AccessibleWrap::get_accSelection(VARIANT
 
 STDMETHODIMP
 AccessibleWrap::get_accDefaultAction(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszDefaultAction)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pszDefaultAction)
+    return E_INVALIDARG;
+
   *pszDefaultAction = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
@@ -795,16 +834,24 @@ AccessibleWrap::accLocation(
       /* [out] */ long __RPC_FAR *pxLeft,
       /* [out] */ long __RPC_FAR *pyTop,
       /* [out] */ long __RPC_FAR *pcxWidth,
       /* [out] */ long __RPC_FAR *pcyHeight,
       /* [optional][in] */ VARIANT varChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pxLeft || !pyTop || !pcxWidth || !pcyHeight)
+    return E_INVALIDARG;
+
+  *pxLeft = 0;
+  *pyTop = 0;
+  *pcxWidth = 0;
+  *pcyHeight = 0;
+
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
 
   if (xpAccessible->IsDefunct())
@@ -829,30 +876,30 @@ AccessibleWrap::accNavigate(
       /* [optional][in] */ VARIANT varStart,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarEndUpAt)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pvarEndUpAt)
     return E_INVALIDARG;
 
+  VariantInit(pvarEndUpAt);
+
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* accessible = GetXPAccessibleFor(varStart);
   if (!accessible)
     return E_INVALIDARG;
 
   if (accessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  VariantInit(pvarEndUpAt);
-
   Accessible* navAccessible = nullptr;
-  uint32_t xpRelation = 0;
+  int32_t xpRelation = -1;
 
   switch(navDir) {
     case NAVDIR_FIRSTCHILD:
       if (!nsAccUtils::MustPrune(accessible))
         navAccessible = accessible->FirstChild();
       break;
     case NAVDIR_LASTCHILD:
       if (!nsAccUtils::MustPrune(accessible))
@@ -924,17 +971,17 @@ AccessibleWrap::accNavigate(
       break;
 
     default:
       return E_INVALIDARG;
   }
 
   pvarEndUpAt->vt = VT_EMPTY;
 
-  if (xpRelation) {
+  if (xpRelation >= 0) {
     Relation rel = RelationByType(xpRelation);
     navAccessible = rel.Next();
   }
 
   if (!navAccessible)
     return E_FAIL;
 
   pvarEndUpAt->pdispVal = NativeAccessible(navAccessible);
@@ -947,16 +994,19 @@ AccessibleWrap::accNavigate(
 STDMETHODIMP
 AccessibleWrap::accHitTest(
       /* [in] */ long xLeft,
       /* [in] */ long yTop,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!pvarChild)
+    return E_INVALIDARG;
+
   VariantInit(pvarChild);
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* accessible = ChildAtPoint(xLeft, yTop, eDirectChild);
 
   // if we got a child
@@ -1108,32 +1158,35 @@ AccessibleWrap::get_relations(long aMaxR
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::role(long *aRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aRole)
+    return E_INVALIDARG;
+
   *aRole = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
 #define ROLE(_geckoRole, stringRole, atkRole, macRole, \
              msaaRole, ia2Role, nameRule) \
   case roles::_geckoRole: \
     *aRole = ia2Role; \
     break;
 
   a11y::role geckoRole = Role();
   switch (geckoRole) {
 #include "RoleMap.h"
     default:
-      MOZ_NOT_REACHED("Unknown role.");
+      MOZ_CRASH("Unknown role.");
   };
 
 #undef ROLE
 
   // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
   // the IA2 role a ROLE_OUTLINEITEM.
   if (geckoRole == roles::ROW) {
     Accessible* xpParent = Parent();
@@ -1181,16 +1234,23 @@ AccessibleWrap::scrollToPoint(enum IA2Co
 
 STDMETHODIMP
 AccessibleWrap::get_groupPosition(long *aGroupLevel,
                                   long *aSimilarItemsInGroup,
                                   long *aPositionInGroup)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aGroupLevel || !aSimilarItemsInGroup || !aPositionInGroup)
+    return E_INVALIDARG;
+
+  *aGroupLevel = 0;
+  *aSimilarItemsInGroup = 0;
+  *aPositionInGroup = 0;
+
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   GroupPos groupPos = GroupPosition();
 
   // Group information for accessibles having level only (like html headings
   // elements) isn't exposed by this method. AT should look for 'level' object
   // attribute.
@@ -1206,16 +1266,19 @@ AccessibleWrap::get_groupPosition(long *
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_states(AccessibleStates *aStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aStates)
+    return E_INVALIDARG;
+
   *aStates = 0;
 
   // XXX: bug 344674 should come with better approach that we have here.
 
   uint64_t state = State();
 
   if (state & states::INVALID)
     *aStates |= IA2_STATE_INVALID_ENTRY;
@@ -1251,99 +1314,122 @@ AccessibleWrap::get_states(AccessibleSta
   if (state & states::SUPPORTS_AUTOCOMPLETION)
     *aStates |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
   if (state & states::TRANSIENT)
     *aStates |= IA2_STATE_TRANSIENT;
   if (state & states::VERTICAL)
     *aStates |= IA2_STATE_VERTICAL;
   if (state & states::CHECKED)
     *aStates |= IA2_STATE_CHECKABLE;
+  if (state & states::PINNED)
+    *aStates |= IA2_STATE_PINNED;
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_extendedRole(BSTR *aExtendedRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aExtendedRole)
+    return E_INVALIDARG;
+
   *aExtendedRole = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_localizedExtendedRole(BSTR *aLocalizedExtendedRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aLocalizedExtendedRole)
+    return E_INVALIDARG;
+
   *aLocalizedExtendedRole = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_nExtendedStates(long *aNExtendedStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aNExtendedStates)
+    return E_INVALIDARG;
+
   *aNExtendedStates = 0;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_extendedStates(long aMaxExtendedStates,
                                    BSTR **aExtendedStates,
                                    long *aNExtendedStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aExtendedStates || !aNExtendedStates)
+    return E_INVALIDARG;
+
   *aExtendedStates = nullptr;
   *aNExtendedStates = 0;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
                                             BSTR** aLocalizedExtendedStates,
                                             long* aNLocalizedExtendedStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aLocalizedExtendedStates || !aNLocalizedExtendedStates)
+    return E_INVALIDARG;
+
   *aLocalizedExtendedStates = nullptr;
   *aNLocalizedExtendedStates = 0;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_uniqueID(long *uniqueID)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!uniqueID)
+    return E_INVALIDARG;
+
   *uniqueID = - reinterpret_cast<intptr_t>(UniqueID());
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_windowHandle(HWND *aWindowHandle)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aWindowHandle)
+    return E_INVALIDARG;
+
   *aWindowHandle = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aWindowHandle = GetHWNDFor(this);
   return S_OK;
 
@@ -1371,16 +1457,19 @@ AccessibleWrap::get_indexInParent(long *
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_locale(IA2Locale *aLocale)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aLocale)
+    return E_INVALIDARG;
+
   // Language codes consist of a primary code and a possibly empty series of
   // subcodes: language-code = primary-code ( "-" subcode )*
   // Two-letter primary codes are reserved for [ISO639] language abbreviations.
   // Any two-letter subcode is understood to be a [ISO3166] country code.
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
@@ -1418,16 +1507,19 @@ AccessibleWrap::get_locale(IA2Locale *aL
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_attributes(BSTR *aAttributes)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aAttributes)
+    return E_INVALIDARG;
+
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
   *aAttributes = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
@@ -1437,23 +1529,29 @@ AccessibleWrap::get_attributes(BSTR *aAt
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IDispatch
 
 STDMETHODIMP
 AccessibleWrap::GetTypeInfoCount(UINT *pctinfo)
 {
+  if (!pctinfo)
+    return E_INVALIDARG;
+
   *pctinfo = 1;
   return S_OK;
 }
 
 STDMETHODIMP
 AccessibleWrap::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
 {
+  if (!ppTInfo)
+    return E_INVALIDARG;
+
   *ppTInfo = nullptr;
 
   if (iTInfo != 0)
     return DISP_E_BADINDEX;
 
   ITypeInfo * typeInfo = GetTI(lcid);
   if (!typeInfo)
     return E_FAIL;
@@ -1727,24 +1825,23 @@ AccessibleWrap::GetXPAccessibleFor(const
   if (aVarChild.lVal < 0) {
     // Convert child ID to unique ID.
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
 
     // Document.
     if (IsDoc())
       return AsDoc()->GetAccessibleByUniqueIDInSubtree(uniqueID);
 
-    // ARIA document.
-    if (ARIARole() == roles::DOCUMENT) {
+    // ARIA document and menu popups.
+    if (ARIARole() == roles::DOCUMENT || IsMenuPopup()) {
       DocAccessible* document = Document();
       Accessible* child =
         document->GetAccessibleByUniqueIDInSubtree(uniqueID);
 
-      // Check whether the accessible for the given ID is a child of ARIA
-      // document.
+      // Check whether the accessible for the given ID is a child.
       Accessible* parent = child ? child->Parent() : nullptr;
       while (parent && parent != document) {
         if (parent == this)
           return child;
 
         parent = parent->Parent();
       }
     }
--- a/accessible/src/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -43,16 +43,19 @@ ApplicationAccessibleWrap::NativeAttribu
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IUnknown
 
 STDMETHODIMP
 ApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_IAccessibleApplication == iid) {
     *ppv = static_cast<IAccessibleApplication*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -62,16 +65,19 @@ ApplicationAccessibleWrap::QueryInterfac
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleApplication
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appName(BSTR* aName)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aName)
+    return E_INVALIDARG;
+
   *aName = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
   nsresult rv = GetAppName(name);
   if (NS_FAILED(rv))
@@ -86,16 +92,19 @@ ApplicationAccessibleWrap::get_appName(B
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appVersion(BSTR* aVersion)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aVersion)
+    return E_INVALIDARG;
+
   *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
   nsresult rv = GetAppVersion(version);
   if (NS_FAILED(rv))
@@ -110,16 +119,19 @@ ApplicationAccessibleWrap::get_appVersio
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_toolkitName(BSTR* aName)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aName)
+    return E_INVALIDARG;
+
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
   nsresult rv = GetPlatformName(name);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
@@ -132,16 +144,19 @@ ApplicationAccessibleWrap::get_toolkitNa
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_toolkitVersion(BSTR* aVersion)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aVersion)
+    return E_INVALIDARG;
+
   *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
   nsresult rv = GetPlatformVersion(version);
   if (NS_FAILED(rv))
--- a/accessible/src/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/DocAccessibleWrap.cpp
@@ -59,32 +59,38 @@ STDMETHODIMP_(ULONG) DocAccessibleWrap::
 {
   return nsAccessNode::Release();
 }
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 DocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = nullptr;
 
   if (IID_ISimpleDOMDocument != iid)
     return HyperTextAccessibleWrap::QueryInterface(iid, ppv);
 
   statistics::ISimpleDOMUsed();
   *ppv = static_cast<ISimpleDOMDocument*>(this);
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
   return S_OK;
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aURL)
+    return E_INVALIDARG;
+
   *aURL = nullptr;
 
   nsAutoString URL;
   nsresult rv = GetURL(URL);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (URL.IsEmpty())
@@ -96,16 +102,19 @@ DocAccessibleWrap::get_URL(/* [out] */ B
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_title( /* [out] */ BSTR __RPC_FAR *aTitle)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aTitle)
+    return E_INVALIDARG;
+
   *aTitle = nullptr;
 
   nsAutoString title;
   nsresult rv = GetTitle(title);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   *aTitle = ::SysAllocStringLen(title.get(), title.Length());
@@ -114,16 +123,19 @@ DocAccessibleWrap::get_title( /* [out] *
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_mimeType(/* [out] */ BSTR __RPC_FAR *aMimeType)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aMimeType)
+    return E_INVALIDARG;
+
   *aMimeType = nullptr;
 
   nsAutoString mimeType;
   nsresult rv = GetMimeType(mimeType);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (mimeType.IsEmpty())
@@ -135,16 +147,19 @@ DocAccessibleWrap::get_mimeType(/* [out]
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_docType(/* [out] */ BSTR __RPC_FAR *aDocType)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aDocType)
+    return E_INVALIDARG;
+
   *aDocType = nullptr;
 
   nsAutoString docType;
   nsresult rv = GetDocType(docType);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (docType.IsEmpty())
@@ -157,16 +172,19 @@ DocAccessibleWrap::get_docType(/* [out] 
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_nameSpaceURIForID(/* [in] */  short aNameSpaceID,
   /* [out] */ BSTR __RPC_FAR *aNameSpaceURI)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aNameSpaceURI)
+    return E_INVALIDARG;
+
   *aNameSpaceURI = nullptr;
 
   if (aNameSpaceID < 0)
     return E_INVALIDARG;  // -1 is kNameSpaceID_Unknown
 
   nsAutoString nameSpaceURI;
   nsresult rv = GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI);
   if (NS_FAILED(rv))
@@ -183,27 +201,33 @@ DocAccessibleWrap::get_nameSpaceURIForID
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *aCommaSeparatedMediaTypes)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (!aCommaSeparatedMediaTypes)
+    return E_INVALIDARG;
+
   *aCommaSeparatedMediaTypes = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
+  if (!pszValue)
+    return E_INVALIDARG;
+
   // For backwards-compat, we still support old MSAA hack to provide URL in accValue
   *pszValue = nullptr;
   // Check for real value first
   HRESULT hr = AccessibleWrap::get_accValue(varChild, pszValue);
   if (FAILED(hr) || *pszValue || varChild.lVal != CHILDID_SELF)
     return hr;
   // If document is being used to create a widget, don't use the URL hack
   roles::Role role = Role();
--- a/accessible/src/xpcom/Makefile.in
+++ b/accessible/src/xpcom/Makefile.in
@@ -5,32 +5,31 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_xpcom_s
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 EXTRA_MDDEPEND_FILES = xpcAccEvents.pp
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
   -I$(srcdir)/../generic \
   $(NULL)
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_ENABLE_GTK
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../windows/msaa \
   $(NULL)
--- a/accessible/src/xpcom/moz.build
+++ b/accessible/src/xpcom/moz.build
@@ -12,8 +12,10 @@ EXPORTS += [
 
 CPP_SOURCES += [
     'nsAccessibleRelation.cpp',
     'xpcAccEvents.cpp',
     'xpcAccessibleTable.cpp',
     'xpcAccessibleTableCell.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_xpcom_s'
+
--- a/accessible/src/xul/Makefile.in
+++ b/accessible/src/xul/Makefile.in
@@ -5,17 +5,16 @@
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-LIBRARY_NAME = accessibility_xul_s
 LIBXUL_LIBRARY = 1
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
@@ -24,17 +23,17 @@ LOCAL_INCLUDES = \
   -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   -I$(srcdir)/../../../layout/xul/tree// \
   $(NULL)
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_ENABLE_GTK
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../windows/msaa \
   -I$(srcdir)/../windows/ia2 \
--- a/accessible/src/xul/XULElementAccessibles.cpp
+++ b/accessible/src/xul/XULElementAccessibles.cpp
@@ -90,17 +90,17 @@ XULLabelAccessible::NativeState()
 }
 
 Relation
 XULLabelAccessible::RelationByType(uint32_t aType)
 {
   Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
   if (aType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
     // Caption is the label for groupbox
-    nsIContent *parent = mContent->GetParent();
+    nsIContent* parent = mContent->GetFlattenedTreeParent();
     if (parent && parent->Tag() == nsGkAtoms::caption) {
       Accessible* parent = Parent();
       if (parent && parent->Role() == roles::GROUPING)
         rel.AppendTarget(parent);
     }
   }
 
   return rel;
--- a/accessible/src/xul/XULFormControlAccessible.cpp
+++ b/accessible/src/xul/XULFormControlAccessible.cpp
@@ -162,33 +162,23 @@ XULButtonAccessible::ContainerWidget() c
 ////////////////////////////////////////////////////////////////////////////////
 // XULButtonAccessible: Accessible protected
 
 void
 XULButtonAccessible::CacheChildren()
 {
   // In general XUL button has not accessible children. Nevertheless menu
   // buttons can have button (@type="menu-button") and popup accessibles
-  // (@type="menu-button" or @type="menu").
+  // (@type="menu-button", @type="menu" or columnpicker.
 
   // XXX: no children until the button is menu button. Probably it's not
   // totally correct but in general AT wants to have leaf buttons.
-  bool isMenu = mContent->AttrValueIs(kNameSpaceID_None,
-                                       nsGkAtoms::type,
-                                       nsGkAtoms::menu,
-                                       eCaseMatters);
 
-  bool isMenuButton = isMenu ?
-    false :
-    mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                          nsGkAtoms::menuButton, eCaseMatters);
-
-  NS_ENSURE_TRUE_VOID(mDoc);
-  if (!isMenu && !isMenuButton)
-    return;
+  bool isMenuButton = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                                            nsGkAtoms::menuButton, eCaseMatters);
 
   Accessible* menupopup = nullptr;
   Accessible* button = nullptr;
 
   TreeWalker walker(this, mContent);
 
   Accessible* child = nullptr;
   while ((child = walker.NextChild())) {
@@ -249,17 +239,17 @@ XULDropmarkerAccessible::ActionCount()
 }
 
 bool
 XULDropmarkerAccessible::DropmarkerOpen(bool aToggleOpen)
 {
   bool isOpen = false;
 
   nsCOMPtr<nsIDOMXULButtonElement> parentButtonElement =
-    do_QueryInterface(mContent->GetParent());
+    do_QueryInterface(mContent->GetFlattenedTreeParent());
 
   if (parentButtonElement) {
     parentButtonElement->GetOpen(&isOpen);
     if (aToggleOpen)
       parentButtonElement->SetOpen(!isOpen);
   }
   else {
     nsCOMPtr<nsIDOMXULMenuListElement> parentMenuListElement =
@@ -835,16 +825,20 @@ XULTextFieldAccessible::CacheChildren()
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTextFieldAccessible: HyperTextAccessible protected
 
 already_AddRefed<nsFrameSelection>
 XULTextFieldAccessible::FrameSelection()
 {
   nsCOMPtr<nsIContent> inputContent(GetInputField());
+  NS_ASSERTION(inputContent, "No input content");
+  if (!inputContent)
+    return nullptr;
+
   nsIFrame* frame = inputContent->GetPrimaryFrame();
   return frame ? frame->GetFrameSelection() : nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTextFieldAccessible protected
 
 already_AddRefed<nsIContent>
--- a/accessible/src/xul/XULListboxAccessible.cpp
+++ b/accessible/src/xul/XULListboxAccessible.cpp
@@ -98,17 +98,17 @@ XULColumnItemAccessible::DoAction(uint8_
 ////////////////////////////////////////////////////////////////////////////////
 // XULListboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULListboxAccessible::
   XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
 {
-  nsIContent* parentContent = mContent->GetParent();
+  nsIContent* parentContent = mContent->GetFlattenedTreeParent();
   if (parentContent) {
     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
       do_QueryInterface(parentContent);
     if (autoCompletePopupElm)
       mGenericTypes |= eAutoCompletePopup;
   }
 }
 
--- a/accessible/src/xul/XULMenuAccessible.cpp
+++ b/accessible/src/xul/XULMenuAccessible.cpp
@@ -434,17 +434,17 @@ XULMenupopupAccessible::
   XULMenupopupAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   XULSelectControlAccessible(aContent, aDoc)
 {
   nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
   if (menuPopupFrame && menuPopupFrame->IsMenu())
     mType = eMenuPopupType;
 
   // May be the anonymous <menupopup> inside <menulist> (a combobox)
-  mSelectControl = do_QueryInterface(mContent->GetParent());
+  mSelectControl = do_QueryInterface(mContent->GetFlattenedTreeParent());
   if (!mSelectControl)
     mGenericTypes &= ~eSelect;
 }
 
 uint64_t
 XULMenupopupAccessible::NativeState()
 {
   uint64_t state = Accessible::NativeState();
@@ -472,17 +472,17 @@ XULMenupopupAccessible::NativeState()
 }
 
 ENameValueFlag
 XULMenupopupAccessible::NativeName(nsString& aName)
 {
   nsIContent* content = mContent;
   while (content && aName.IsEmpty()) {
     content->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
-    content = content->GetParent();
+    content = content->GetFlattenedTreeParent();
   }
 
   return eNameOK;
 }
 
 role
 XULMenupopupAccessible::NativeRole()
 {
--- a/accessible/src/xul/XULTabAccessible.cpp
+++ b/accessible/src/xul/XULTabAccessible.cpp
@@ -78,23 +78,29 @@ XULTabAccessible::NativeRole()
 uint64_t
 XULTabAccessible::NativeState()
 {
   // Possible states: focused, focusable, unavailable(disabled), offscreen.
 
   // get focus and disable status from base class
   uint64_t state = AccessibleWrap::NativeState();
 
-  // Check whether the tab is selected
+  // Check whether the tab is selected and/or pinned
   nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
   if (tab) {
     bool selected = false;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       state |= states::SELECTED;
+
+    if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
+                              nsGkAtoms::_true, eCaseMatters))
+      state |= states::PINNED;
+
   }
+
   return state;
 }
 
 uint64_t
 XULTabAccessible::NativeInteractiveState() const
 {
   uint64_t state = Accessible::NativeInteractiveState();
   return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE;
--- a/accessible/src/xul/moz.build
+++ b/accessible/src/xul/moz.build
@@ -16,8 +16,10 @@ CPP_SOURCES += [
     'XULMenuAccessible.cpp',
     'XULSelectControlAccessible.cpp',
     'XULSliderAccessible.cpp',
     'XULTabAccessible.cpp',
     'XULTreeAccessible.cpp',
     'XULTreeGridAccessible.cpp',
 ]
 
+LIBRARY_NAME = 'accessibility_xul_s'
+
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -17,17 +17,21 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="../common.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // aria
-      testAttrs("atomic", {"atomic" : "true"}, true);
+      testAttrs("atomic", {"atomic" : "true", "container-atomic" : "true"}, true);
+      testAttrs(getNode("atomic").firstChild, {"container-atomic" : "true"}, true);
+      testAbsentAttrs("atomic_false", {"atomic" : "false", "container-atomic" : "false"});
+      testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic" : "false"});
+
       testAttrs("autocomplete", {"autocomplete" : "true"}, true);
       testAttrs("checkbox", {"checkable" : "true"}, true); 
       testAttrs("checkedCheckbox", {"checkable" : "true"}, true); 
       testAttrs("checkedMenuitem", {"checkable" : "true"}, true); 
       testAttrs("checkedOption", {"checkable" : "true"}, true); 
       testAttrs("checkedRadio", {"checkable" : "true"}, true); 
       testAttrs("checkedTreeitem", {"checkable" : "true"}, true); 
       testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
@@ -169,17 +173,18 @@ https://bugzilla.mozilla.org/show_bug.cg
     Mozilla Bug 838407
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <!-- aria -->
-  <div id="atomic" aria-atomic="true"></div>
+  <div id="atomic" aria-atomic="true">live region</div>
+  <div id="atomic_false" aria-atomic="false">live region</div>
   <div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
   <div id="checkbox" role="checkbox"></div>
   <div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
   <div id="checkedMenuitem" role="menuitem" aria-checked="true"></div>
   <div id="checkedOption" role="option" aria-checked="true"></div>
   <div id="checkedRadio" role="radio" aria-checked="true"></div>
   <div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>
   <div id="dropeffect" aria-dropeffect="copy"></div>
--- a/accessible/tests/mochitest/events/test_docload.html
+++ b/accessible/tests/mochitest/events/test_docload.html
@@ -10,16 +10,35 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
+
+  <script type="application/javascript">
+    // Front end stuff sometimes likes to stuff things in the hidden window(s)
+    // in which case there's accessibles for that content.
+    Components.utils.import("resource://gre/modules/Services.jsm");
+
+    // Force the creation of an accessible for the hidden window's document.
+    var doc = Services.appShell.hiddenDOMWindow.document;
+    gAccRetrieval.getAccessibleFor(doc);
+
+    // The private hidden window will be lazily created that's why we need to do
+    // it here *before* loading '../events.js' or else we'll have a duplicate
+    // reorder event.
+    var privateDoc = Services.appShell.hiddenPrivateDOMWindow.document;
+
+    // Force the creation of an accessible for the private hidden window's doc.
+    gAccRetrieval.getAccessibleFor(privateDoc);
+  </script>
+
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
     function changeIframeSrc(aIdentifier, aURL)
@@ -174,16 +193,22 @@
         var accTree = {
           role: ROLE_APP_ROOT,
           children: [
             {
               role: ROLE_CHROME_WINDOW
             },
             {
               role: ROLE_CHROME_WINDOW
+            },
+            {
+              role: ROLE_CHROME_WINDOW
+            },
+            {
+              role: ROLE_CHROME_WINDOW
             }
           ]
         };
 
         testAccessibleTree(this.mRootAcc, accTree);
 
         var dlgDoc = this.mDialog.document;
         ok(isAccessibleInCache(dlgDoc),
--- a/accessible/tests/mochitest/hittest/Makefile.in
+++ b/accessible/tests/mochitest/hittest/Makefile.in
@@ -9,15 +9,16 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir	= @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_A11Y_FILES = \
 		test_browser.html \
 		test_general.html \
+		test_menu.xul \
 		test_zoom_text.html \
 		test_zoom_tree.xul \
 		test_zoom.html \
 		zoom_tree.xul \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/hittest/test_menu.xul
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Hit testing for XUL menus">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+  <script type="application/javascript"
+          src="../layout.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    function openMenu(aMenuID, aMenuPopupID, aMenuItemID)
+    {
+      this.menuNode = getNode(aMenuID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, this.menuNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        this.menuNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        hitTest(aMenuPopupID, aMenuItemID, aMenuItemID);
+      }
+
+      this.getID = function openMenu_invoke()
+      {
+        return "open menu '" + aMenuID + "' and do hit testing";
+      }
+    }
+
+    function closeMenu(aID, aSubID, aSub2ID)
+    {
+      this.menuNode = getNode(aID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, document)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        this.menuNode.open = false;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        testStates(aID, 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN);
+        testStates(aSubID, STATE_INVISIBLE, 0, STATE_OFFSCREEN);
+        testStates(aSub2ID, STATE_INVISIBLE, 0, STATE_OFFSCREEN);
+      }
+
+      this.getID = function openMenu_invoke()
+      {
+        return "open menu and test states";
+      }
+    }
+
+    var gQueue = null;
+    function doTest()
+    {
+      if (LINUX) {
+        ok(true, "No tests is running on Linux");
+        SimpleTest.finish();
+        return;
+      }
+
+      gQueue = new eventQueue();
+      gQueue.push(new openMenu("mi_file1", "mp_file1", "mi_file1.1"));
+      gQueue.push(new openMenu("mi_file1.2", "mp_file1.2", "mi_file1.2.1"));
+      gQueue.push(new closeMenu("mi_file1", "mi_file1.1", "mi_file1.2.1"));
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+     <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=670087"
+         title="AccessibleObjectFromPoint returns incorrect accessible for popup menus">
+        Bug 670087
+     </a>
+
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+
+      <menubar>
+        <menu label="File" id="mi_file1">
+          <menupopup id="mp_file1">
+            <menuitem label="SubFile" id="mi_file1.1"/>
+            <menu label="SubFile2" id="mi_file1.2">
+              <menupopup style="max-height: 5em;" id="mp_file1.2">
+                <menuitem label="SubSubFile" id="mi_file1.2.1"/>
+                <menuitem label="SubSubFile2" id="mi_file1.2.2"/>
+                <menuitem label="SubSubFile3" id="mi_file1.2.3"/>
+                <menuitem label="SubSubFile4" id="mi_file1.2.4"/>
+              </menupopup>
+            </menu>
+          </menupopup>
+        </menu>
+      </menubar>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/accessible/tests/mochitest/jsat/Makefile.in
+++ b/accessible/tests/mochitest/jsat/Makefile.in
@@ -8,15 +8,17 @@ topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_A11Y_FILES =\
 jsatcommon.js \
-utterance.js \
+output.js \
 test_alive.html \
+test_braille.html \
 test_explicit_names.html \
+test_tables.html \
 test_utterance_order.html \
 $(NULL)
 
 include $(topsrcdir)/config/rules.mk
rename from accessible/tests/mochitest/jsat/utterance.js
rename to accessible/tests/mochitest/jsat/output.js
--- a/accessible/tests/mochitest/jsat/utterance.js
+++ b/accessible/tests/mochitest/jsat/output.js
@@ -1,70 +1,81 @@
 const Cu = Components.utils;
 const PREF_UTTERANCE_ORDER = "accessibility.accessfu.utterance";
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import("resource://gre/modules/accessibility/UtteranceGenerator.jsm",
-  this);
+Cu.import("resource://gre/modules/accessibility/OutputGenerator.jsm", this);
 
 /**
- * Test context utterance generation.
+ * Test context output generation.
  *
- * @param expected {Array} expected utterance.
+ * @param expected {Array} expected output.
  * @param aAccOrElmOrID    identifier to get an accessible to test.
  * @param aOldAccOrElmOrID optional identifier to get an accessible relative to
  *                         the |aAccOrElmOrID|.
+ * @param aGenerator       the output generator to use when generating accessible
+ *                         output
  *
  * Note: if |aOldAccOrElmOrID| is not provided, the |aAccOrElmOrID| must be
  * scoped to the "root" element in markup.
  */
-function testContextUtterance(expected, aAccOrElmOrID, aOldAccOrElmOrID) {
+function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator) {
   aOldAccOrElmOrID = aOldAccOrElmOrID || "root";
   var accessible = getAccessible(aAccOrElmOrID);
   var oldAccessible = getAccessible(aOldAccOrElmOrID);
   var context = new PivotContext(accessible, oldAccessible);
-  var utterance = UtteranceGenerator.genForContext(context);
-  isDeeply(utterance, expected,
-    "Context utterance is correct for " + aAccOrElmOrID);
+  var output = aGenerator.genForContext(context);
+  isDeeply(output, expected,
+    "Context output is correct for " + aAccOrElmOrID);
 }
 
 /**
- * Test object utterance generated array that includes names.
- * Note: test ignores utterances without the name.
+ * Test object output generated array that includes names.
+ * Note: test ignores outputs without the name.
  *
  * @param aAccOrElmOrID identifier to get an accessible to test.
+ * @param aGenerator    the output generator to use when generating accessible
+ *                      output
  */
-function testObjectUtterance(aAccOrElmOrID) {
+function testObjectOutput(aAccOrElmOrID, aGenerator) {
   var accessible = getAccessible(aAccOrElmOrID);
-  var utterance = UtteranceGenerator.genForObject(accessible);
-  var utteranceOrder;
+  var context = new PivotContext(accessible);
+  var output = aGenerator.genForObject(accessible, context);
+  var outputOrder;
   try {
-    utteranceOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);
+    outputOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);
   } catch (ex) {
     // PREF_UTTERANCE_ORDER not set.
-    utteranceOrder = 0;
+    outputOrder = 0;
   }
-  var expectedNameIndex = utteranceOrder === 0 ? utterance.length - 1 : 0;
-  var nameIndex = utterance.indexOf(accessible.name);
+  var expectedNameIndex = outputOrder === 0 ? output.length - 1 : 0;
+  var nameIndex = output.indexOf(accessible.name);
 
   if (nameIndex > -1) {
-    ok(utterance.indexOf(accessible.name) === expectedNameIndex,
-      "Object utterance is correct for " + aAccOrElmOrID);
+    ok(output.indexOf(accessible.name) === expectedNameIndex,
+      "Object output is correct for " + aAccOrElmOrID);
   }
 }
 
 /**
- * Test object and context utterance for an accessible.
+ * Test object and context output for an accessible.
  *
- * @param expected {Array} expected utterance.
+ * @param expected {Array} expected output.
  * @param aAccOrElmOrID    identifier to get an accessible to test.
  * @param aOldAccOrElmOrID optional identifier to get an accessible relative to
  *                         the |aAccOrElmOrID|.
+ * @param aOutputKind      the type of output
  */
-function testUtterance(expected, aAccOrElmOrID, aOldAccOrElmOrID) {
-  testContextUtterance(expected, aAccOrElmOrID, aOldAccOrElmOrID);
-  // Just need to test object utterance for individual
+function testOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aOutputKind) {
+  var generator;
+  if (aOutputKind === 1) {
+    generator = UtteranceGenerator;
+  } else {
+    generator = BrailleGenerator;
+  }
+  testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, generator);
+  // Just need to test object output for individual
   // accOrElmOrID.
   if (aOldAccOrElmOrID) {
     return;
   }
-  testObjectUtterance(aAccOrElmOrID);
-}
\ No newline at end of file
+  testObjectOutput(aAccOrElmOrID, generator);
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/test_braille.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=876475
+-->
+  <head>
+    <title>[AccessFu] braille generation test</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" type="text/css"
+          href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+    <script type="application/javascript"
+            src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript"
+            src="../common.js"></script>
+    <script type="application/javascript"
+            src="./output.js"></script>
+    <script type="application/javascript">
+
+      function doTest() {
+        // Test the following accOrElmOrID (with optional old accOrElmOrID).
+        // Note: each accOrElmOrID entry maps to a unique object braille
+        // generator function within the BrailleGenerator.
+        var tests = [{
+          accOrElmOrID: "link",
+          expected: [["lnk", "Link"], ["Link", "lnk"]]
+        },{
+          accOrElmOrID: "button",
+          expected: [["btn", "I am a button"], ["I am a button", "btn"]]
+        },{
+          accOrElmOrID: "password_input",
+          expected: [["passwdtxt", "Secret Password"], ["Secret Password", "passwdtxt"]]
+        },{
+          accOrElmOrID: "checkbox_unchecked",
+          expected: [["( )", "checkboxtext"], ["checkboxtext", "( )"]]
+        },{
+          accOrElmOrID: "checkbox_checked",
+          expected: [["(x)", "some more checkbox text"], ["some more checkbox text", "(x)"]]
+        },{
+          accOrElmOrID: "radio_unselected",
+          expected: [["( )", "any old radio button"], ["any old radio button", "( )"]]
+        },{
+          accOrElmOrID: "radio_selected",
+          expected: [["(x)", "a unique radio button"], ["a unique radio button", "(x)"]]
+        },{
+          accOrElmOrID: "togglebutton_notpressed",
+          expected: [["( )", "I ain't pressed"], ["I ain't pressed", "( )"]]
+        },{
+          accOrElmOrID: "togglebutton_pressed",
+          expected: [["(x)", "I am pressed!"], ["I am pressed!", "(x)"]]
+        },{
+          accOrElmOrID: "ul_li_one",
+          expected: [["*", "ul item 1"], ["*", "ul item 1"]]
+        },{
+          accOrElmOrID: "ol_li_one",
+          expected: [["1.", "ol item 1"], ["1.", "ol item 1"]]
+        },{
+          accOrElmOrID: "textarea",
+          expected: [["txtarea", "Here lies treasure."], ["Here lies treasure.", "txtarea"]]
+        }];
+
+        // Test all possible braille order preference values.
+        tests.forEach(function run(test) {
+          var brailleOrderValues = [0, 1];
+          brailleOrderValues.forEach(
+            function testBrailleOrder(brailleOrder) {
+              SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, brailleOrder);
+              var expected = test.expected[brailleOrder];
+              testOutput(expected, test.accOrElmOrID, test.oldAccOrElmOrID, 2);
+            }
+          );
+        });
+
+        // If there was an original utterance order preference, revert to it.
+        SpecialPowe