Merge m-c to fig. [r=karma]
authorSriram Ramasubramanian <sriram@mozilla.com>
Wed, 03 Jul 2013 17:08:31 -0700
changeset 151366 49e0f1320f140e265d766baa9f18778f726264b6
parent 151365 b689792b6fd2070e77774ce4a65e9bb52cad0a1d (current diff)
parent 144933 38767daf33dd71d71264de5ca052592ccf2c05b8 (diff)
child 151367 e4ab0a67ccaef00a58ced6023d7f684c3f047279
push idunknown
push userunknown
push dateunknown
reviewerskarma
milestone25.0a1
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.
+        SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
+        SimpleTest.finish();
+      }
+
+      SimpleTest.waitForExplicitFinish();
+      addA11yLoadEvent(doTest);
+
+    </script>
+  </head>
+  <body>
+    <div id="root">
+      <p id="display"></p>
+      <div id="content" style="display: none"></div>
+      <pre id="test"></pre>
+      <a href="example.com" id="link">Link</a>
+      <button id="button">I am a button</button>
+      <label for="password_input">Secret Password</label><input id="password_input" type="password"></input>
+      <label for="checkbox_unchecked">checkboxtext</label><input id="checkbox_unchecked" type="checkbox"></input>
+      <label for="checkbox_checked">some more checkbox text</label><input id="checkbox_checked" type="checkbox" checked></input>
+      <label for="radio_unselected">any old radio button</label><input id="radio_unselected" type="radio"></input>
+      <label for="radio_selected">a unique radio button</label><input id="radio_selected" type="radio" checked></input>
+      <div id="togglebutton_notpressed" aria-pressed="false" role="button" tabindex="-1">I ain't pressed</div>
+      <div id="togglebutton_pressed" aria-pressed="true" role="button" tabindex="-1">I am pressed!</div>
+      <ol id="ordered_list">
+        <li id="ol_li_one">ol item 1</li>
+        <li id="ol_li_two">ol item 2</li>
+        <li id="ol_li_three">ol item 3</li>
+        <li id="ol_li_three">ol item 4</li>
+      </ol>
+      <ul id="unordered_list">
+        <li id="ul_li_one">ul item 1</li>
+        <li id="ul_li_two">ul item 2</li>
+        <li id="ul_li_three">ul item 3</li>
+        <li id="ul_li_three">ul item 4</li>
+      </ul>
+      <textarea id="textarea" cols="80" rows="5">
+        Here lies treasure.
+      </textarea>
+   </div>
+  </body>
+</html>
--- a/accessible/tests/mochitest/jsat/test_explicit_names.html
+++ b/accessible/tests/mochitest/jsat/test_explicit_names.html
@@ -4,17 +4,17 @@
 
   <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="utterance.js"></script>
+          src="output.js"></script>
   <script type="application/javascript">
 
     function doTest() {
       // Test the following accOrElmOrID.
       var tests = [{
         accOrElmOrID: "anchor1",
         expected: ["link", "title"]
       }, {
@@ -36,67 +36,70 @@
         accOrElmOrID: "heading1",
         expected: ["heading level 1", "Test heading", "This is the heading."]
       }, {
         accOrElmOrID: "heading2",
         expected: ["heading level 1", "This is the heading."]
       }, {
         accOrElmOrID: "list",
         expected: ["list 2 items", "Test List", "First item", "Top of the list",
-          "1.", "list one", "Last item", "2.", "list two"]
+          "Last item", "2.", "list two"]
       }, {
         accOrElmOrID: "dlist",
         expected: ["definition list 0.5 items", "Test Definition List",
           "dd one"]
       }, {
         accOrElmOrID: "li_one",
         expected: ["list 2 items", "Test List", "First item", "Top of the list"]
       }, {
         accOrElmOrID: "li_two",
         expected: ["list 2 items", "Test List", "Last item", "2.", "list two"]
       }, {
         accOrElmOrID: "cell",
-        expected: ["table", "Fruits and vegetables", "List of Fruits",
-          "list 4 items","First item", "link", "Apples", "link", "Bananas",
-          "link", "Peaches", "Last item", "link", "Plums"]
+        expected: ["table with 1 column and 1 row", "Fruits and vegetables",
+          "Column 1 Row 1", "List of Fruits", "list 4 items", "First item",
+          "link", "Apples", "link", "Bananas", "link", "Peaches", "Last item",
+          "link", "Plums"]
       }, {
         accOrElmOrID: "app.net",
         expected: ["list 2 items", "First item", "link", "star", "Last item",
           "link", "repost"]
       }, {
         // Test pivot to list from li_one.
         accOrElmOrID: "list",
         oldAccOrElmOrID: "li_one",
         expected: ["list 2 items", "Test List", "First item", "Top of the list",
-          "1.", "list one", "Last item", "2.", "list two"]
+          "Last item", "2.", "list two"]
       }, {
         // Test pivot to li_one from list.
         accOrElmOrID: "li_one",
         oldAccOrElmOrID: "list",
-        expected: ["list 2 items", "Test List", "First item", "Top of the list"]
+        expected: ["First item", "Top of the list"]
       }, {
         // Test pivot to "apples" link from the table cell.
         accOrElmOrID: "apples",
         oldAccOrElmOrID: "cell",
-        expected: ["List of Fruits", "list 4 items", "First item", "link",
-          "Apples"]
+        expected: ["list 4 items", "First item", "link", "Apples"]
       }, {
         // Test pivot to the table cell from the "apples" link.
         accOrElmOrID: "cell",
         oldAccOrElmOrID: "apples",
         expected: ["List of Fruits", "list 4 items", "First item", "link",
           "Apples", "link", "Bananas", "link", "Peaches", "Last item", "link",
           "Plums"]
       }];
 
+      SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, 0);
+
       // Test various explicit names vs the utterance generated from subtrees.
       tests.forEach(function run(test) {
-        testUtterance(test.expected, test.accOrElmOrID, test.oldAccOrElmOrID);
+        testOutput(test.expected, test.accOrElmOrID, test.oldAccOrElmOrID, 1);
       });
 
+      SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -146,21 +149,21 @@
             </li>
           </ul>
         </td>
       </tr>
     </table>
     <!-- app.net -->
     <ul id="app.net" class="unstyled ul-horizontal yui3-u fixed-right ta-right" style="list-style-type: none;">
       <li class="yui3-u">
-        <a href="#star" data-starred="0" data-star-button="1" data-post-id="5098826">
-          <i aria-label="star" class="icon-star-empty"></i>
+        <a href="#star" data-starred="0" data-star-button="1" data-post-id="5098826" aria-label="star">
+          Garbage
         </a>
       </li>
       <li class="yui3-u repost">
         <a href="#repost" title="repost" data-repost-button="1" data-reposted="0" data-post-id="5098826">
           <i aria-label="repost" class="icon-repost"></i>
         </a>
       </li>
     </ul>
   </div>
 </body>
-</html>
\ No newline at end of file
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/test_tables.html
@@ -0,0 +1,297 @@
+<html>
+<head>
+  <title>[AccessFu] Improve reading of table semantics</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="output.js"></script>
+  <script type="application/javascript">
+
+    function doTest() {
+      // Test the following accOrElmOrID.
+      var tests = [{
+        accOrElmOrID: "table1",
+        expectedUtterance: [["table with 2 columns and 2 rows",
+          "Column 1 Row 1", "col1", "Column 2 Row 1", "col2",
+          "Column 1 Row 2 col1", "cell1", "Column 2 Row 2 col2", "cell2"], [
+          "col1", "Column 1 Row 1", "col2", "Column 2 Row 1", "cell1",
+          "Column 1 Row 2 col1", "cell2", "Column 2 Row 2 col2",
+          "table with 2 columns and 2 rows"]],
+        expectedBraille: [["tbl 2c 2r", "c1r1", "col1", "c2r1", "col2",
+          "c1r2 col1", "cell1", "c2r2 col2", "cell2"], ["col1", "c1r1", "col2",
+          "c2r1", "cell1", "c1r2 col1", "cell2", "c2r2 col2", "tbl 2c 2r"]]
+      }, {
+        accOrElmOrID: "table2",
+        expectedUtterance: [["table with 2 columns and 2 rows",
+          "Column 1 Row 1 col1", "cell1", "Column 2 Row 1 col2",
+          "table with 1 column and 2 rows", "Column 1 Row 1", "colheader",
+          "Column 1 Row 2 colheader", "bla", "Column 1 Row 2", "col1",
+          "Column 2 Row 2", "col2"], ["cell1", "Column 1 Row 1 col1",
+          "colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
+          "table with 1 column and 2 rows", "Column 2 Row 1 col2", "col1",
+          "Column 1 Row 2", "col2", "Column 2 Row 2",
+          "table with 2 columns and 2 rows"]],
+        expectedBraille: [["tbl 2c 2r", "c1r1 col1", "cell1", "c2r1 col2",
+          "tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader", "bla", "c1r2",
+          "col1", "c2r2", "col2"], ["cell1", "c1r1 col1", "colheader", "c1r1",
+          "bla", "c1r2 colheader", "tbl 1c 2r", "c2r1 col2", "col1", "c1r2",
+          "col2", "c2r2", "tbl 2c 2r"]]
+      }, {
+        accOrElmOrID: "table3",
+        expectedUtterance: [["table with 2 columns and 2 rows",
+          "Column 2 Row 1 col2", "table with 1 column and 2 rows",
+          "Column 1 Row 1", "colheader", "Column 1 Row 2 colheader", "bla"], [
+          "colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
+          "table with 1 column and 2 rows", "Column 2 Row 1 col2",
+          "table with 2 columns and 2 rows"]],
+        expectedBraille: [["tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader",
+          "bla"], ["colheader", "c1r1", "bla", "c1r2 colheader", "tbl 1c 2r"]]
+      }, {
+        accOrElmOrID: "table4",
+        expectedUtterance: [["table with 4 columns and 3 rows",
+          "Column 1 Row 1", "col1", "Column 2 Row 1", "col2", "Column 3 Row 1",
+          "col3", "Column 1 Row 2 spans 2 columns col1", "row1",
+          "Column 3 Row 2 col3 row1", "cell1",
+          "Column 4 Row 2 spans 2 rows row1", "cell2", "Column 1 Row 3 col1",
+          "row2", "Column 2 Row 3 col2 row2", "cell3",
+          "Column 3 Row 3 col3 row2", "cell4"], ["col1"