Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 30 Jan 2015 12:22:33 -0500
changeset 255568 d7e156a7a0a6d050119885d972b048c09d267e74
parent 255490 6d5fbdc6f5ef889bae768700d7ca898957fc9834 (current diff)
parent 255567 6b9ee0581d401b4403ae582eb9a69658a0785b38 (diff)
child 255569 6161f6b9dbbeae41c29cd55373c92a687f2893f7
child 255587 b014f2ac0664a2b03b144e391539ecb143102188
child 255665 bb30dc4d6962d4116422043927fedb906473ab8e
child 255681 9d4fa68b4cd97036cd9b7ca4eb535e1e46084129
push id721
push userjlund@mozilla.com
push dateTue, 21 Apr 2015 23:03:33 +0000
treeherdermozilla-release@d27c9211ebb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone38.0a1
first release with
nightly linux32
d7e156a7a0a6 / 38.0a1 / 20150131030230 / files
nightly linux64
d7e156a7a0a6 / 38.0a1 / 20150131030230 / files
nightly mac
d7e156a7a0a6 / 38.0a1 / 20150131030230 / files
nightly win32
d7e156a7a0a6 / 38.0a1 / 20150131030230 / files
nightly win64
d7e156a7a0a6 / 38.0a1 / 20150131030230 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c. a=merge
configure.in
media/webrtc/trunk/base/base.Makefile
media/webrtc/trunk/base/base.gyp
media/webrtc/trunk/base/base.target.mk
media/webrtc/trunk/webrtc/build/find_depot_tools.py
media/webrtc/trunk/webrtc/common_audio/resampler/Android.mk
media/webrtc/trunk/webrtc/common_audio/signal_processing/Android.mk
media/webrtc/trunk/webrtc/common_audio/signal_processing/spl_version.c
media/webrtc/trunk/webrtc/common_audio/vad/Android.mk
media/webrtc/trunk/webrtc/common_video/libyuv/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/cng/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/g711/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/g722/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/ilbc/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/main/source/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/pcm16b/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_amr.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_amr.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_amrwb.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_amrwb.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_celt.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_celt.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_cng.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_cng.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_codec_database.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_codec_database.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_dtmf_detection.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_dtmf_detection.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_dtmf_playout.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_dtmf_playout.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g722.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g722.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7221.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7221.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7221c.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7221c.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g729.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g729.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7291.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_g7291.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_generic_codec.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_generic_codec.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_gsmfr.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_gsmfr.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_ilbc.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_ilbc.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_isac.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_isac.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_isac_macros.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_neteq.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_neteq.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_neteq_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_opus.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_opus.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcm16b.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcm16b.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcma.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcma.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcmu.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_pcmu.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_red.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_red.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_resampler.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_resampler.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_speex.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/acm_speex.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/audio_coding_module.gypi
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h
media/webrtc/trunk/webrtc/modules/audio_coding/main/test/ACMTest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/test/TestFEC.cc
media/webrtc/trunk/webrtc/modules/audio_coding/main/test/TestFEC.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/Android.mk
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/accelerate.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/automode.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/automode.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/bgn_update.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/buffer_stats.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/bufstats_decision.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/cng_internal.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/codec_db.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/codec_db.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/codec_db_defines.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/correlator.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_logging.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp_helpfunctions.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp_helpfunctions.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_buffer.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_tonegen.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_tonegen.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/expand.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/interface/webrtc_neteq.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/interface/webrtc_neteq_internal.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mcu.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mcu_address_init.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mcu_dsp_common.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mcu_dsp_common.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mcu_reset.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/merge.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/min_distortion.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mix_voice_unvoice.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mute_signal.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_defines.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_error_codes.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_statistics.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_unittests.isolate
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/normal.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/packet_buffer.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/peak_detection.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/preemptive_expand.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/random_vector.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/recin.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/recout.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/rtcp.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/rtp.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/rtp.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/set_fs.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/signal_mcu.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/split_and_insert.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/NETEQTEST_NetEQClass.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/NETEQTEST_NetEQClass.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/NetEqRTPplay.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/RTPanalyze.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/ptypes.txt
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/unmute_signal.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/webrtc_neteq.c
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/webrtc_neteq_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/OWNERS
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/accelerate.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/accelerate.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_impl.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_impl.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_unittests.isolate
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_fax.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_fax.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_normal.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/defines.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_buffer.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_buffer.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_buffer_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_tone_generator.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_tone_generator.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_tone_generator_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/interface/neteq.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_audio_decoder.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_audio_vector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_buffer_level_filter.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_decoder_database.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_delay_manager.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_delay_peak_detector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_dtmf_buffer.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_dtmf_tone_generator.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_external_decoder_pcm16b.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_packet_buffer.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_payload_splitter.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq.gypi
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_external_decoder_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_impl.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_impl_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_stereo_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/normal.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/normal.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/normal_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet_buffer.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet_buffer.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet_buffer_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/preemptive_expand.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/rtcp.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/rtcp.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/statistics_calculator.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/statistics_calculator.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/NETEQTEST_DummyRTPpacket.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/NETEQTEST_DummyRTPpacket.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/NETEQTEST_RTPpacket.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/NETEQTEST_RTPpacket.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/PayloadTypes.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPanalyze.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPcat.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPchange.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPencode.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPjitter.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/RTPtimeshift.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/delay_tool/parse_delay_file.m
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/delay_tool/plot_neteq_delay.m
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/neteq_performance_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/neteq_speed_test.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/rtp_to_text.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler_unittest.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/audio_loop.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/audio_loop.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/input_audio_file.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/input_audio_file.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_rtpplay.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/rtp_generator.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h
media/webrtc/trunk/webrtc/modules/audio_conference_mixer/source/Android.mk
media/webrtc/trunk/webrtc/modules/audio_device/Android.mk
media/webrtc/trunk/webrtc/modules/audio_device/ios/audio_device_ios.cc
media/webrtc/trunk/webrtc/modules/audio_processing/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/aec/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/aecm/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/agc/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/echo_cancellation_impl_wrapper.h
media/webrtc/trunk/webrtc/modules/audio_processing/ns/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/test/android/apmtest/jni/Android.mk
media/webrtc/trunk/webrtc/modules/audio_processing/utility/Android.mk
media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_mac.mm
media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_null.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_win.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info_null.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/mac/desktop_device_info_mac.h
media/webrtc/trunk/webrtc/modules/desktop_capture/mac/desktop_device_info_mac.mm
media/webrtc/trunk/webrtc/modules/desktop_capture/mac/osx_version.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/mac/osx_version.h
media/webrtc/trunk/webrtc/modules/desktop_capture/win/desktop_device_info_win.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/win/desktop_device_info_win.h
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.h
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.h
media/webrtc/trunk/webrtc/modules/media_file/source/Android.mk
media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h
media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/rtp_to_ntp.cc
media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/rtp_to_ntp_unittest.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/Android.mk
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/h264_information.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/h264_information.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/rtp_sender_h264.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/H264/rtp_sender_h264.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc
media/webrtc/trunk/webrtc/modules/utility/source/Android.mk
media/webrtc/trunk/webrtc/modules/video_capture/Android.mk
media/webrtc/trunk/webrtc/modules/video_capture/android/OWNERS
media/webrtc/trunk/webrtc/modules/video_capture/ios/video_capture_ios_objc.h
media/webrtc/trunk/webrtc/modules/video_capture/ios/video_capture_ios_objc.mm
media/webrtc/trunk/webrtc/modules/video_coding/codecs/i420/main/source/Android.mk
media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/Android.mk
media/webrtc/trunk/webrtc/modules/video_coding/main/source/Android.mk
media/webrtc/trunk/webrtc/modules/video_coding/main/source/timestamp_extrapolator.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/source/timestamp_extrapolator.h
media/webrtc/trunk/webrtc/modules/video_coding/main/test/pcap_file_reader.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/test/pcap_file_reader.h
media/webrtc/trunk/webrtc/modules/video_coding/main/test/pcap_file_reader_unittest.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/test/rtp_file_reader.cc
media/webrtc/trunk/webrtc/modules/video_coding/main/test/rtp_file_reader.h
media/webrtc/trunk/webrtc/modules/video_coding/main/test/rtp_file_reader_unittest.cc
media/webrtc/trunk/webrtc/modules/video_coding/utility/Android.mk
media/webrtc/trunk/webrtc/modules/video_coding/utility/exp_filter.cc
media/webrtc/trunk/webrtc/modules/video_coding/utility/include/exp_filter.h
media/webrtc/trunk/webrtc/modules/video_processing/main/OWNERS
media/webrtc/trunk/webrtc/modules/video_processing/main/source/Android.mk
media/webrtc/trunk/webrtc/modules/video_processing/main/source/denoising.cc
media/webrtc/trunk/webrtc/modules/video_processing/main/source/denoising.h
media/webrtc/trunk/webrtc/modules/video_processing/main/test/unit_test/denoising_test.cc
media/webrtc/trunk/webrtc/modules/video_render/Android.mk
media/webrtc/trunk/webrtc/modules/video_render/android/OWNERS
media/webrtc/trunk/webrtc/system_wrappers/interface/constructor_magic.h
media/webrtc/trunk/webrtc/system_wrappers/interface/thread_annotations.h
media/webrtc/trunk/webrtc/system_wrappers/source/Android.mk
media/webrtc/trunk/webrtc/system_wrappers/source/unittest_utilities.h
media/webrtc/trunk/webrtc/system_wrappers/source/unittest_utilities_unittest.cc
media/webrtc/trunk/webrtc/test/Android.mk
media/webrtc/trunk/webrtc/test/buildbot_tests.py
media/webrtc/trunk/webrtc/test/flags.cc
media/webrtc/trunk/webrtc/test/flags.h
media/webrtc/trunk/webrtc/test/libtest/helpers/bit_flip_encryption.cc
media/webrtc/trunk/webrtc/test/libtest/helpers/random_encryption.cc
media/webrtc/trunk/webrtc/test/libtest/include/bit_flip_encryption.h
media/webrtc/trunk/webrtc/test/libtest/include/random_encryption.h
media/webrtc/trunk/webrtc/test/libtest/libtest.gyp
media/webrtc/trunk/webrtc/test/mac/run_tests.mm
media/webrtc/trunk/webrtc/test/run_tests.h
media/webrtc/trunk/webrtc/test/testsupport/android/root_path_android.cc
media/webrtc/trunk/webrtc/test/testsupport/android/root_path_android_chromium.cc
media/webrtc/trunk/webrtc/test/w3c/getusermedia_conformance_test.html
media/webrtc/trunk/webrtc/test/w3c/getusermedia_conformance_test.js
media/webrtc/trunk/webrtc/test/w3c/peerconnection_conformance_test.html
media/webrtc/trunk/webrtc/video/call_tests.cc
media/webrtc/trunk/webrtc/video_engine/Android.mk
media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
media/webrtc/trunk/webrtc/video_engine/test/auto_test/android/Android.mk
media/webrtc/trunk/webrtc/video_engine/test/auto_test/android/jni/Android.mk
media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/Android.mk
media/webrtc/trunk/webrtc/voice_engine/Android.mk
media/webrtc/trunk/webrtc/voice_engine/include/mock/mock_voe_connection_observer.h
media/webrtc/trunk/webrtc/voice_engine/include/voe_call_report.h
media/webrtc/trunk/webrtc/voice_engine/include/voe_encryption.h
media/webrtc/trunk/webrtc/voice_engine/output_mixer_internal.cc
media/webrtc/trunk/webrtc/voice_engine/output_mixer_internal.h
media/webrtc/trunk/webrtc/voice_engine/output_mixer_unittest.cc
media/webrtc/trunk/webrtc/voice_engine/test/android/OWNERS
media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/Android.mk
media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/jni/Android.mk
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/Android.mk
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fuzz/rtp_fuzz_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/call_report_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/encryption_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/manual_hold_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/neteq_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/network_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_unit_test.cc
media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_unit_test.h
media/webrtc/trunk/webrtc/voice_engine/test/cmd_test/Android.mk
media/webrtc/trunk/webrtc/voice_engine/voe_call_report_impl.cc
media/webrtc/trunk/webrtc/voice_engine/voe_call_report_impl.h
media/webrtc/trunk/webrtc/voice_engine/voe_encryption_impl.cc
media/webrtc/trunk/webrtc/voice_engine/voe_encryption_impl.h
media/webrtc/trunk/webrtc/voice_engine/voe_neteq_stats_unittest.cc
modules/libpref/init/all.js
testing/web-platform/meta/battery-status/battery-interface-idlharness.html.ini
testing/web-platform/meta/gamepad/idlharness.html.ini
testing/web-platform/meta/notifications/interfaces.html.ini
testing/web-platform/meta/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html.ini
testing/web-platform/meta/webaudio/the-audio-api/the-delaynode-interface/idl-test.html.ini
testing/web-platform/meta/webaudio/the-audio-api/the-gainnode-interface/idl-test.html.ini
testing/web-platform/meta/websockets/extended-payload-length.html.ini
testing/web-platform/meta/webstorage/idlharness.html.ini
testing/web-platform/meta/webstorage/storage_local_security.html.ini
testing/web-platform/tests/webstorage/iframe/local_security_iframe.html
testing/web-platform/tests/webstorage/storage_local_security.html
testing/web-platform/tests/workers/interfaces/WorkerUtils/navigator/001.html
xpcom/base/Makefile.in
xpcom/base/nsErrorAssertsC.c
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1018324 - Clobber should fix burning tree
+Bug 1109248 - This needed a CLOBBER on Windows and OSX.
--- a/b2g/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -20,16 +20,22 @@ DEFINES += -DJAREXT=
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
 
 # Set MSVC dlls version to package, if any.
 ifdef WIN32_REDIST_DIR
 ifdef MOZ_NO_DEBUG_RTL
 DEFINES += -DMOZ_PACKAGE_MSVC_DLLS=1
 DEFINES += -DMSVC_C_RUNTIME_DLL=$(MSVC_C_RUNTIME_DLL)
 DEFINES += -DMSVC_CXX_RUNTIME_DLL=$(MSVC_CXX_RUNTIME_DLL)
+ifdef MSVC_APPCRT_DLL
+DEFINES += -DMSVC_APPCRT_DLL=$(MSVC_APPCRT_DLL)
+endif
+ifdef MSVC_DESKTOPCRT_DLL
+DEFINES += -DMSVC_DESKTOPCRT_DLL=$(MSVC_DESKTOPCRT_DLL)
+endif
 endif
 endif
 
 ifdef MOZ_DEBUG
 DEFINES += -DMOZ_DEBUG=1
 endif
 
 ifdef ENABLE_MARIONETTE
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -69,16 +69,22 @@
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
 #else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #ifdef XP_WIN32
 #if MOZ_PACKAGE_MSVC_DLLS
 @BINPATH@/@MSVC_C_RUNTIME_DLL@
 @BINPATH@/@MSVC_CXX_RUNTIME_DLL@
+#ifdef MSVC_APPCRT_DLL
+@BINPATH@/@MSVC_APPCRT_DLL@
+#endif
+#ifdef MSVC_DESKTOPCRT_DLL
+@BINPATH@/@MSVC_DESKTOPCRT_DLL@
+#endif
 #endif
 #endif
 #ifdef MOZ_SHARED_MOZGLUE
 @BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
 #endif
 #ifdef MOZ_REPLACE_MALLOC
 #ifndef MOZ_JEMALLOC3
 @BINPATH@/@DLL_PREFIX@replace_jemalloc@DLL_SUFFIX@
--- a/browser/components/places/tests/browser/head.js
+++ b/browser/components/places/tests/browser/head.js
@@ -387,18 +387,19 @@ function promiseSetToolbarVisibility(aTo
         aToolbar.removeEventListener("transitionend", listener);
         resolve();
       }
     }
 
     let transitionProperties =
       window.getComputedStyle(aToolbar).transitionProperty.split(", ");
     if (isToolbarVisible(aToolbar) != aVisible &&
-        (transitionProperties.includes("max-height") ||
-         transitionProperties.includes("all"))) {
+        transitionProperties.some(
+          prop => prop == "max-height" || prop == "all"
+        )) {
       // Just because max-height is a transitionable property doesn't mean
       // a transition will be triggered, but it's more likely.
       aToolbar.addEventListener("transitionend", listener);
       setToolbarVisibility(aToolbar, aVisible);
       return;
     }
 
     // No animation to wait for
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -68,16 +68,22 @@ endif
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
 
 # Set MSVC dlls version to package, if any.
 ifdef WIN32_REDIST_DIR
 ifdef MOZ_NO_DEBUG_RTL
 DEFINES += -DMOZ_PACKAGE_MSVC_DLLS=1
 DEFINES += -DMSVC_C_RUNTIME_DLL=$(MSVC_C_RUNTIME_DLL)
 DEFINES += -DMSVC_CXX_RUNTIME_DLL=$(MSVC_CXX_RUNTIME_DLL)
+ifdef MSVC_APPCRT_DLL
+DEFINES += -DMSVC_APPCRT_DLL=$(MSVC_APPCRT_DLL)
+endif
+ifdef MSVC_DESKTOPCRT_DLL
+DEFINES += -DMSVC_DESKTOPCRT_DLL=$(MSVC_DESKTOPCRT_DLL)
+endif
 endif
 endif
 
 ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET)))
 DEFINES += -DMOZ_SHARED_MOZGLUE=1
 endif
 
 ifdef NECKO_WIFI
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -95,16 +95,22 @@
 #else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #ifdef XP_WIN32
 @BINPATH@/plugin-hang-ui@BIN_SUFFIX@
 #if MOZ_PACKAGE_MSVC_DLLS
 @BINPATH@/@MSVC_C_RUNTIME_DLL@
 @BINPATH@/@MSVC_CXX_RUNTIME_DLL@
+#ifdef MSVC_APPCRT_DLL
+@BINPATH@/@MSVC_APPCRT_DLL@
+#endif
+#ifdef MSVC_DESKTOPCRT_DLL
+@BINPATH@/@MSVC_DESKTOPCRT_DLL@
+#endif
 #endif
 #endif
 #ifndef MOZ_NATIVE_ICU
 #ifdef MOZ_SHARED_ICU
 #ifdef XP_WIN
 @BINPATH@/icudt@MOZ_ICU_DBG_SUFFIX@@MOZ_ICU_VERSION@.dll
 @BINPATH@/icuin@MOZ_ICU_DBG_SUFFIX@@MOZ_ICU_VERSION@.dll
 @BINPATH@/icuuc@MOZ_ICU_DBG_SUFFIX@@MOZ_ICU_VERSION@.dll
--- a/build/gyp.mozbuild
+++ b/build/gyp.mozbuild
@@ -17,19 +17,21 @@ gyp_vars = {
     'clang_use_chrome_plugins': 0,
     'enable_protobuf': 0,
     'include_tests': 0,
     'enable_android_opensl': 1,
     'enable_android_opensl_output': 0,
     # use_system_lib* still seems to be in use in trunk/build
     'use_system_libjpeg': 0,
     'use_system_libvpx': 0,
+    'build_json': 0,
     'build_libjpeg': 0,
+    'build_libyuv': 0,
     'build_libvpx': 0,
-    'build_libyuv': 0,
+    'build_ssl': 0,
     'libyuv_dir': '/media/libyuv',
     'yuv_disable_avx2': 0 if CONFIG['HAVE_X86_AVX2'] else 1,
     # don't use openssl
     'use_openssl': 0,
 
     # saves 4MB when webrtc_trace is off
     'enable_lazy_trace_alloc': 1 if CONFIG['RELEASE_BUILD'] else 0,
 
@@ -42,17 +44,17 @@ gyp_vars = {
 
     'moz_widget_toolkit_gonk': 0,
     'moz_webrtc_omx': 0,
 
     # (for vp8) chromium sets to 0 also
     'use_temporal_layers': 0,
 
     # Creates AEC internal sample dump files in current directory
-    'aec_debug_dump': 1,
+    'aec_debug_dump': 0,
 
     # Enable and force use of hardware AEC
     'hardware_aec_ns': 1 if CONFIG['MOZ_WEBRTC_HARDWARE_AEC_NS'] else 0,
 
     # codec enable/disables:
     'include_g711': 1,
     'include_opus': 1,
     'include_g722': 1,
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -4,16 +4,18 @@
 
 include $(topsrcdir)/config/rules.mk
 
 ifdef WIN32_REDIST_DIR
 
 REDIST_FILES = \
   $(MSVC_C_RUNTIME_DLL) \
   $(MSVC_CXX_RUNTIME_DLL) \
+  $(MSVC_APPCRT_DLL) \
+  $(MSVC_DESKTOPCRT_DLL) \
   $(NULL)
 
 libs-preqs = \
   $(call mkdir_deps,$(FINAL_TARGET)) \
   $(NULL)
 
 libs:: $(libs-preqs)
 	install --preserve-timestamps $(foreach f,$(REDIST_FILES),'$(WIN32_REDIST_DIR)'/$(f)) $(FINAL_TARGET)
--- a/configure.in
+++ b/configure.in
@@ -492,24 +492,44 @@ case "$target" in
         AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
         AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
 
         if test "$_CC_MAJOR_VERSION" = "18" -a "$_CC_BUILD_VERSION" -ge "30723"; then
             _CC_SUITE=12
             MSVS_VERSION=2013
             MSVC_C_RUNTIME_DLL=msvcr120.dll
             MSVC_CXX_RUNTIME_DLL=msvcp120.dll
+        elif test "$_CC_MAJOR_VERSION" = "19"; then
+            _CC_SUITE=14
+            MSVS_VERSION=2015
+            MSVC_C_RUNTIME_DLL=vcruntime140.dll
+            MSVC_CXX_RUNTIME_DLL=msvcp140.dll
+            MSVC_APPCRT_DLL=appcrt140.dll
+            MSVC_DESKTOPCRT_DLL=desktopcrt140.dll
+
+            # -Wv:18 disables all warnings introduced after VS2013
+            # See http://blogs.msdn.com/b/vcblog/archive/2014/11/12/improvements-to-warnings-in-the-c-compiler.aspx
+            CFLAGS="$CFLAGS -Wv:18"
+            CXXFLAGS="$CXXFLAGS -Wv:18"
+
+            # https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h
+            # for dbghelp.h, imagehlp.h, and shobj.h
+            # C4091: 'typedef ': ignored on left of '' when no variable is declared
+            CFLAGS="$CFLAGS -wd4091"
+            CXXFLAGS="$CXXFLAGS -wd4091"
         else
             AC_MSG_ERROR([This version (${_CC_MAJOR_VERSION}.${_CC_MINOR_VERSION}.${_CC_BUILD_VERSION}) of the MSVC compiler is unsupported.
 You must install Visual C++ 2013 Update 3 or newer in order to build.
 See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         fi
         AC_SUBST(MSVS_VERSION)
         AC_SUBST(MSVC_C_RUNTIME_DLL)
         AC_SUBST(MSVC_CXX_RUNTIME_DLL)
+        AC_SUBST(MSVC_APPCRT_DLL)
+        AC_SUBST(MSVC_DESKTOPCRT_DLL)
 
         # Disable SEH on clang-cl because it doesn't implement them yet.
         if test -z "$CLANG_CL"; then
             AC_DEFINE(HAVE_SEH_EXCEPTIONS)
         else
             # Send our CFLAGS to NSS
             MOZ_CFLAGS_NSS=1
             AC_DEFINE_UNQUOTED(GTEST_HAS_SEH, 0)
--- a/dom/base/nsLineBreaker.cpp
+++ b/dom/base/nsLineBreaker.cpp
@@ -140,16 +140,23 @@ nsLineBreaker::FlushCurrentWord()
   mCurrentWord.Clear();
   mTextItems.Clear();
   mCurrentWordContainsComplexChar = false;
   mCurrentWordContainsMixedLang = false;
   mCurrentWordLanguage = nullptr;
   return NS_OK;
 }
 
+// If the aFlags parameter to AppendText has all these bits set,
+// then we don't need to worry about finding break opportunities
+// in the appended text.
+#define NO_BREAKS_NEEDED_FLAGS (BREAK_SUPPRESS_INITIAL | \
+                                BREAK_SUPPRESS_INSIDE | \
+                                BREAK_SKIP_SETTING_NO_BREAKS)
+
 nsresult
 nsLineBreaker::AppendText(nsIAtom* aHyphenationLanguage, const char16_t* aText, uint32_t aLength,
                           uint32_t aFlags, nsILineBreakSink* aSink)
 {
   NS_ASSERTION(aLength > 0, "Appending empty text...");
 
   uint32_t offset = 0;
 
@@ -179,33 +186,35 @@ nsLineBreaker::AppendText(nsIAtom* aHyph
       return rv;
   }
 
   nsAutoTArray<uint8_t,4000> breakState;
   if (aSink) {
     if (!breakState.AppendElements(aLength))
       return NS_ERROR_OUT_OF_MEMORY;
   }
-  
+
+  bool noCapitalizationNeeded = true;
   nsTArray<bool> capitalizationState;
   if (aSink && (aFlags & BREAK_NEED_CAPITALIZATION)) {
     if (!capitalizationState.AppendElements(aLength))
       return NS_ERROR_OUT_OF_MEMORY;
     memset(capitalizationState.Elements(), false, aLength*sizeof(bool));
+    noCapitalizationNeeded = false;
   }
 
   uint32_t start = offset;
   bool noBreaksNeeded = !aSink ||
-    (aFlags == (BREAK_SUPPRESS_INITIAL | BREAK_SUPPRESS_INSIDE | BREAK_SKIP_SETTING_NO_BREAKS) &&
+    ((aFlags & NO_BREAKS_NEEDED_FLAGS) == NO_BREAKS_NEEDED_FLAGS &&
      !mBreakHere && !mAfterBreakableSpace);
-  if (noBreaksNeeded) {
+  if (noBreaksNeeded && noCapitalizationNeeded) {
     // Skip to the space before the last word, since either the break data
     // here is not needed, or no breaks are set in the sink and there cannot
-    // be any breaks in this chunk; all we need is the context for the next
-    // chunk (if any)
+    // be any breaks in this chunk; and we don't need to do word-initial
+    // capitalization. All we need is the context for the next chunk (if any).
     offset = aLength;
     while (offset > start) {
       --offset;
       if (IsSpace(aText[offset]))
         break;
     }
   }
   uint32_t wordStart = offset;
@@ -218,17 +227,17 @@ nsLineBreaker::AppendText(nsIAtom* aHyph
     hyphenator = nsHyphenationManager::Instance()->GetHyphenator(aHyphenationLanguage);
   }
 
   for (;;) {
     char16_t ch = aText[offset];
     bool isSpace = IsSpace(ch);
     bool isBreakableSpace = isSpace && !(aFlags & BREAK_SUPPRESS_INSIDE);
 
-    if (aSink) {
+    if (aSink && !noBreaksNeeded) {
       breakState[offset] =
         mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ||
         (mWordBreak == nsILineBreaker::kWordBreak_BreakAll)  ?
           gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL :
           gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE;
     }
     mBreakHere = false;
     mAfterBreakableSpace = isBreakableSpace;
@@ -247,17 +256,17 @@ nsLineBreaker::AppendText(nsIAtom* aHyph
             breakState[wordStart] = currentStart;
           }
           if (hyphenator) {
             FindHyphenationPoints(hyphenator,
                                   aText + wordStart, aText + offset,
                                   breakState.Elements() + wordStart);
           }
         }
-        if (aFlags & BREAK_NEED_CAPITALIZATION) {
+        if (!noCapitalizationNeeded) {
           SetupCapitalization(aText + wordStart, offset - wordStart,
                               capitalizationState.Elements() + wordStart);
         }
       }
       wordHasComplexChar = false;
       ++offset;
       if (offset >= aLength)
         break;
@@ -279,20 +288,21 @@ nsLineBreaker::AppendText(nsIAtom* aHyph
         // Ensure that the break-before for this word is written out
         offset = wordStart + 1;
         UpdateCurrentWordLanguage(aHyphenationLanguage);
         break;
       }
     }
   }
 
-  if (!noBreaksNeeded) {
-    // aSink must not be null
-    aSink->SetBreaks(start, offset - start, breakState.Elements() + start);
-    if (aFlags & BREAK_NEED_CAPITALIZATION) {
+  if (aSink) {
+    if (!noBreaksNeeded) {
+      aSink->SetBreaks(start, offset - start, breakState.Elements() + start);
+    }
+    if (!noCapitalizationNeeded) {
       aSink->SetCapitalization(start, offset - start,
                                capitalizationState.Elements() + start);
     }
   }
   return NS_OK;
 }
 
 void
@@ -360,17 +370,17 @@ nsLineBreaker::AppendText(nsIAtom* aHyph
   nsAutoTArray<uint8_t,4000> breakState;
   if (aSink) {
     if (!breakState.AppendElements(aLength))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   uint32_t start = offset;
   bool noBreaksNeeded = !aSink ||
-    (aFlags == (BREAK_SUPPRESS_INITIAL | BREAK_SUPPRESS_INSIDE | BREAK_SKIP_SETTING_NO_BREAKS) &&
+    ((aFlags & NO_BREAKS_NEEDED_FLAGS) == NO_BREAKS_NEEDED_FLAGS &&
      !mBreakHere && !mAfterBreakableSpace);
   if (noBreaksNeeded) {
     // Skip to the space before the last word, since either the break data
     // here is not needed, or no breaks are set in the sink and there cannot
     // be any breaks in this chunk; all we need is the context for the next
     // chunk (if any)
     offset = aLength;
     while (offset > start) {
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -57,16 +57,23 @@ public:
   }
 
   uint16_t
   Status() const
   {
     return mInternalResponse->GetStatus();
   }
 
+  bool
+  Ok() const
+  {
+    return mInternalResponse->GetStatus() >= 200 &&
+           mInternalResponse->GetStatus() <= 299;
+  }
+
   void
   GetStatusText(nsCString& aStatusText) const
   {
     aStatusText = mInternalResponse->GetStatusText();
   }
 
   InternalHeaders*
   GetInternalHeaders() const
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -510,16 +510,26 @@ HTMLMediaElement::SetMozAudioChannelType
 }
 
 NS_IMETHODIMP_(bool)
 HTMLMediaElement::IsVideo()
 {
   return false;
 }
 
+already_AddRefed<MediaSource>
+HTMLMediaElement::GetMozMediaSourceObject() const
+{
+  nsRefPtr<MediaSource> source;
+  if (IsMediaSourceURI(mLoadingSrc)) {
+    NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source));
+  }
+  return source.forget();
+}
+
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::GetMozSrcObject() const
 {
   NS_ASSERTION(!mSrcAttrStream || mSrcAttrStream->GetStream(),
                "MediaStream should have been set up properly");
   nsRefPtr<DOMMediaStream> stream = mSrcAttrStream;
   return stream.forget();
 }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -528,16 +528,17 @@ public:
     return mIsCasting;
   }
 
   void SetMozIsCasting(bool aShow)
   {
     mIsCasting = aShow;
   }
 
+  already_AddRefed<MediaSource> GetMozMediaSourceObject() const;
   already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
 
   void SetMozSrcObject(DOMMediaStream& aValue);
   void SetMozSrcObject(DOMMediaStream* aValue);
 
   bool MozPreservesPitch() const
   {
     return mPreservesPitch;
--- a/dom/media/MP3FrameParser.cpp
+++ b/dom/media/MP3FrameParser.cpp
@@ -332,16 +332,21 @@ nsresult MP3FrameParser::ParseBuffer(con
   // If we haven't found any MP3 frame data yet, there might be ID3 headers
   // we can skip over.
   if (mMP3Offset < 0) {
     for (const uint8_t *ch = buffer; ch < bufferEnd; ch++) {
       if (mID3Parser.ParseChar(*ch)) {
         // Found an ID3 header. We don't care about the body of the header, so
         // just skip past.
         buffer = ch + mID3Parser.GetHeaderLength() - (ID3_HEADER_LENGTH - 1);
+
+        if (buffer <= ch) {
+          return NS_ERROR_FAILURE;
+        }
+
         ch = buffer;
 
         mTotalID3Size += mID3Parser.GetHeaderLength();
 
         // Yes, this is an MP3!
         mIsMP3 = DEFINITELY_MP3;
 
         mID3Parser.Reset();
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1293,17 +1293,19 @@ void MediaDecoder::ApplyStateToStateMach
       case PLAY_STATE_PLAYING:
         mDecoderStateMachine->Play();
         break;
       case PLAY_STATE_SEEKING:
         mDecoderStateMachine->Seek(mRequestedSeekTarget);
         mRequestedSeekTarget.Reset();
         break;
       default:
-        /* No action needed */
+        // The state machine checks for things like PAUSED in RunStateMachine.
+        // Make sure to keep it in the loop.
+        ScheduleStateMachineThread();
         break;
     }
   }
 }
 
 void MediaDecoder::PlaybackPositionChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaPromise.cpp
+++ b/dom/media/MediaPromise.cpp
@@ -18,10 +18,23 @@ DispatchMediaPromiseRunnable(MediaTaskQu
 }
 
 nsresult
 DispatchMediaPromiseRunnable(nsIEventTarget* aEventTarget, nsIRunnable* aRunnable)
 {
   return aEventTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
 }
 
+void
+AssertOnThread(MediaTaskQueue* aQueue)
+{
+  MOZ_ASSERT(aQueue->IsCurrentThreadIn());
+}
+
+void AssertOnThread(nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsIThread> targetThread = do_QueryInterface(aTarget);
+  MOZ_ASSERT(targetThread, "Don't know how to deal with threadpools etc here");
+  MOZ_ASSERT(NS_GetCurrentThread() == targetThread);
+}
+
 }
 } // namespace mozilla
--- a/dom/media/MediaPromise.h
+++ b/dom/media/MediaPromise.h
@@ -32,16 +32,21 @@ extern PRLogModuleInfo* gMediaPromiseLog
   PR_LOG(gMediaPromiseLog, PR_LOG_DEBUG, (x, ##__VA_ARGS__))
 
 class MediaTaskQueue;
 namespace detail {
 
 nsresult DispatchMediaPromiseRunnable(MediaTaskQueue* aQueue, nsIRunnable* aRunnable);
 nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable);
 
+#ifdef DEBUG
+void AssertOnThread(MediaTaskQueue* aQueue);
+void AssertOnThread(nsIEventTarget* aTarget);
+#endif
+
 } // namespace detail
 
 /*
  * A promise manages an asynchronous request that may or may not be able to be
  * fulfilled immediately. When an API returns a promise, the consumer may attach
  * callbacks to be invoked (asynchronously, on a specified thread) when the
  * request is either completed (resolved) or cannot be completed (rejected).
  *
@@ -76,25 +81,51 @@ public:
   static nsRefPtr<MediaPromise>
   CreateAndReject(RejectValueType aRejectValue, const char* aRejectSite)
   {
     nsRefPtr<MediaPromise> p = new MediaPromise(aRejectSite);
     p->Reject(aRejectValue, aRejectSite);
     return p;
   }
 
+  class Consumer
+  {
+  public:
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Consumer)
+
+    void Disconnect()
+    {
+      AssertOnDispatchThread();
+      MOZ_RELEASE_ASSERT(!mComplete);
+      mDisconnected = true;
+    }
+
+#ifdef DEBUG
+    virtual void AssertOnDispatchThread() = 0;
+#else
+    void AssertOnDispatchThread() {}
+#endif
+
+  protected:
+    Consumer() : mComplete(false), mDisconnected(false) {}
+    virtual ~Consumer() {}
+
+    bool mComplete;
+    bool mDisconnected;
+  };
+
 protected:
 
   /*
    * A ThenValue tracks a single consumer waiting on the promise. When a consumer
    * invokes promise->Then(...), a ThenValue is created. Once the Promise is
    * resolved or rejected, a {Resolve,Reject}Runnable is dispatched, which
    * invokes the resolve/reject method and then deletes the ThenValue.
    */
-  class ThenValueBase
+  class ThenValueBase : public Consumer
   {
   public:
     class ResolveRunnable : public nsRunnable
     {
     public:
       ResolveRunnable(ThenValueBase* aThenValue, ResolveValueType aResolveValue)
         : mThenValue(aThenValue)
         , mResolveValue(aResolveValue) {}
@@ -103,24 +134,22 @@ protected:
       {
         MOZ_ASSERT(!mThenValue);
       }
 
       NS_IMETHODIMP Run()
       {
         PROMISE_LOG("ResolveRunnable::Run() [this=%p]", this);
         mThenValue->DoResolve(mResolveValue);
-
-        delete mThenValue;
         mThenValue = nullptr;
         return NS_OK;
       }
 
     private:
-      ThenValueBase* mThenValue;
+      nsRefPtr<ThenValueBase> mThenValue;
       ResolveValueType mResolveValue;
     };
 
     class RejectRunnable : public nsRunnable
     {
     public:
       RejectRunnable(ThenValueBase* aThenValue, RejectValueType aRejectValue)
         : mThenValue(aThenValue)
@@ -130,38 +159,30 @@ protected:
       {
         MOZ_ASSERT(!mThenValue);
       }
 
       NS_IMETHODIMP Run()
       {
         PROMISE_LOG("RejectRunnable::Run() [this=%p]", this);
         mThenValue->DoReject(mRejectValue);
-
-        delete mThenValue;
         mThenValue = nullptr;
         return NS_OK;
       }
 
     private:
-      ThenValueBase* mThenValue;
+      nsRefPtr<ThenValueBase> mThenValue;
       RejectValueType mRejectValue;
     };
 
-    explicit ThenValueBase(const char* aCallSite) : mCallSite(aCallSite)
-    {
-      MOZ_COUNT_CTOR(ThenValueBase);
-    }
+    explicit ThenValueBase(const char* aCallSite) : mCallSite(aCallSite) {}
 
     virtual void Dispatch(MediaPromise *aPromise) = 0;
 
   protected:
-    // This may only be deleted by {Resolve,Reject}Runnable::Run.
-    virtual ~ThenValueBase() { MOZ_COUNT_DTOR(ThenValueBase); }
-
     virtual void DoResolve(ResolveValueType aResolveValue) = 0;
     virtual void DoReject(RejectValueType aRejectValue) = 0;
 
     const char* mCallSite;
   };
 
   /*
    * We create two overloads for invoking Resolve/Reject Methods so as to
@@ -213,56 +234,98 @@ protected:
                  : static_cast<nsRunnable*>(new (typename ThenValueBase::RejectRunnable)(this, aPromise->mRejectValue.ref()));
       PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
                   resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
                   runnable.get(), aPromise, this);
       DebugOnly<nsresult> rv = detail::DispatchMediaPromiseRunnable(mResponseTarget, runnable);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 
+#ifdef DEBUG
+  // Can't mark MOZ_OVERRIDE due to bug in clang builders we use for osx b2g desktop. :-(
+  virtual void AssertOnDispatchThread()
+  {
+    detail::AssertOnThread(mResponseTarget);
+  }
+#endif
+
   protected:
     virtual void DoResolve(ResolveValueType aResolveValue) MOZ_OVERRIDE
     {
+      Consumer::mComplete = true;
+      if (Consumer::mDisconnected) {
+        PROMISE_LOG("ThenValue::DoResolve disconnected - bailing out [this=%p]", this);
+        return;
+      }
       InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aResolveValue);
+
+      // Null these out after invoking the callback so that any references are
+      // released predictably on the target thread. Otherwise, they would be
+      // released on whatever thread last drops its reference to the ThenValue,
+      // which may or may not be ok.
+      mResponseTarget = nullptr;
+      mThisVal = nullptr;
     }
 
     virtual void DoReject(RejectValueType aRejectValue) MOZ_OVERRIDE
     {
+      Consumer::mComplete = true;
+      if (Consumer::mDisconnected) {
+        PROMISE_LOG("ThenValue::DoReject disconnected - bailing out [this=%p]", this);
+        return;
+      }
       InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aRejectValue);
+
+      // Null these out after invoking the callback so that any references are
+      // released predictably on the target thread. Otherwise, they would be
+      // released on whatever thread last drops its reference to the ThenValue,
+      // which may or may not be ok.
+      mResponseTarget = nullptr;
+      mThisVal = nullptr;
     }
 
-    virtual ~ThenValue() {}
-
   private:
     nsRefPtr<TargetType> mResponseTarget;
     nsRefPtr<ThisType> mThisVal;
     ResolveMethodType mResolveMethod;
     RejectMethodType mRejectMethod;
   };
 public:
 
   template<typename TargetType, typename ThisType,
            typename ResolveMethodType, typename RejectMethodType>
-  void Then(TargetType* aResponseTarget, const char* aCallSite, ThisType* aThisVal,
-            ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
+  already_AddRefed<Consumer> RefableThen(TargetType* aResponseTarget, const char* aCallSite, ThisType* aThisVal,
+                                         ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
   {
     MutexAutoLock lock(mMutex);
     MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
     mHaveConsumer = true;
-    ThenValueBase* thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
-                                             RejectMethodType>(aResponseTarget, aThisVal,
-                                                               aResolveMethod, aRejectMethod,
-                                                               aCallSite);
+    nsRefPtr<ThenValueBase> thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
+                                                      RejectMethodType>(aResponseTarget, aThisVal,
+                                                                        aResolveMethod, aRejectMethod,
+                                                                        aCallSite);
     PROMISE_LOG("%s invoking Then() [this=%p, thenValue=%p, aThisVal=%p, isPending=%d]",
-                aCallSite, this, thenValue, aThisVal, (int) IsPending());
+                aCallSite, this, thenValue.get(), aThisVal, (int) IsPending());
     if (!IsPending()) {
       thenValue->Dispatch(this);
     } else {
       mThenValues.AppendElement(thenValue);
     }
+
+    return thenValue.forget();
+  }
+
+  template<typename TargetType, typename ThisType,
+           typename ResolveMethodType, typename RejectMethodType>
+  void Then(TargetType* aResponseTarget, const char* aCallSite, ThisType* aThisVal,
+            ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
+  {
+    nsRefPtr<Consumer> c =
+      RefableThen(aResponseTarget, aCallSite, aThisVal, aResolveMethod, aRejectMethod);
+    return;
   }
 
   void ChainTo(already_AddRefed<MediaPromise> aChainedPromise, const char* aCallSite)
   {
     MutexAutoLock lock(mMutex);
     MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
     mHaveConsumer = true;
     nsRefPtr<MediaPromise> chainedPromise = aChainedPromise;
@@ -326,17 +389,17 @@ protected:
     MOZ_ASSERT(mThenValues.IsEmpty());
     MOZ_ASSERT(mChainedPromises.IsEmpty());
   };
 
   const char* mCreationSite; // For logging
   Mutex mMutex;
   Maybe<ResolveValueType> mResolveValue;
   Maybe<RejectValueType> mRejectValue;
-  nsTArray<ThenValueBase*> mThenValues;
+  nsTArray<nsRefPtr<ThenValueBase>> mThenValues;
   nsTArray<nsRefPtr<MediaPromise>> mChainedPromises;
   bool mHaveConsumer;
 };
 
 /*
  * Class to encapsulate a promise for a particular role. Use this as the member
  * variable for a class whose method returns a promise.
  */
@@ -420,13 +483,56 @@ public:
     }
   }
 
 private:
   Monitor* mMonitor;
   nsRefPtr<PromiseType> mPromise;
 };
 
+/*
+ * Class to encapsulate a MediaPromise::Consumer reference. Use this as the member
+ * variable for a class waiting on a media promise.
+ */
+template<typename PromiseType>
+class MediaPromiseConsumerHolder
+{
+public:
+  MediaPromiseConsumerHolder() {}
+  ~MediaPromiseConsumerHolder() { MOZ_ASSERT(!mConsumer); }
+
+  void Begin(already_AddRefed<typename PromiseType::Consumer> aConsumer)
+  {
+    MOZ_RELEASE_ASSERT(!Exists());
+    mConsumer = aConsumer;
+  }
+
+  void Complete()
+  {
+    MOZ_RELEASE_ASSERT(Exists());
+    mConsumer = nullptr;
+  }
+
+  // Disconnects and forgets an outstanding promise. The resolve/reject methods
+  // will never be called.
+  void Disconnect() {
+    MOZ_ASSERT(Exists());
+    mConsumer->Disconnect();
+    mConsumer = nullptr;
+  }
+
+  void DisconnectIfExists() {
+    if (Exists()) {
+      Disconnect();
+    }
+  }
+
+  bool Exists() { return !!mConsumer; }
+
+private:
+  nsRefPtr<typename PromiseType::Consumer> mConsumer;
+};
+
 #undef PROMISE_LOG
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -2472,22 +2472,19 @@ SourceMediaStream::DispatchWhenNotEnough
     aSignalThread->Dispatch(aSignalRunnable, 0);
   }
 }
 
 void
 SourceMediaStream::EndTrack(TrackID aID)
 {
   MutexAutoLock lock(mMutex);
-  // ::EndAllTrackAndFinished() can end these before the sources call this
-  if (!mFinished) {
-    TrackData *track = FindDataForTrack(aID);
-    if (track) {
-      track->mCommands |= TRACK_END;
-    }
+  TrackData *track = FindDataForTrack(aID);
+  if (track) {
+    track->mCommands |= TRACK_END;
   }
   if (auto graph = GraphImpl()) {
     graph->EnsureNextIteration();
   }
 }
 
 void
 SourceMediaStream::AdvanceKnownTracksTime(StreamTime aKnownTime)
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
@@ -33,17 +33,18 @@ PRLogModuleInfo* GetDemuxerLog();
 
 using namespace android;
 typedef android::MediaCodecProxy MediaCodecProxy;
 
 namespace mozilla {
 
 GonkAudioDecoderManager::GonkAudioDecoderManager(
   const mp4_demuxer::AudioDecoderConfig& aConfig)
-  : mAudioChannels(aConfig.channel_count)
+  : GonkDecoderManager()
+  , mAudioChannels(aConfig.channel_count)
   , mAudioRate(aConfig.samples_per_second)
   , mAudioProfile(aConfig.aac_profile)
   , mUseAdts(true)
   , mAudioBuffer(nullptr)
 {
   MOZ_COUNT_CTOR(GonkAudioDecoderManager);
   MOZ_ASSERT(mAudioChannels);
   mUserData.AppendElements(aConfig.audio_specific_config->Elements(),
@@ -92,16 +93,41 @@ GonkAudioDecoderManager::Init(MediaDataD
   if (rv == OK) {
     return mDecoder;
   } else {
     GADM_LOG("Failed to input codec specific data!");
     return nullptr;
   }
 }
 
+status_t
+GonkAudioDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
+{
+  return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->data),
+                         aSample->size,
+                         aSample->composition_timestamp,
+                         0);
+}
+
+void
+GonkAudioDecoderManager::PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample)
+{
+  if (aSample && mUseAdts) {
+    int8_t frequency_index =
+        mp4_demuxer::Adts::GetFrequencyIndex(mAudioRate);
+    bool rv = mp4_demuxer::Adts::ConvertSample(mAudioChannels,
+                                               frequency_index,
+                                               mAudioProfile,
+                                               aSample);
+    if (!rv) {
+      GADM_LOG("Failed to apply ADTS header");
+    }
+  }
+}
+
 nsresult
 GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
   if (!(mAudioBuffer != nullptr && mAudioBuffer->data() != nullptr)) {
     GADM_LOG("Audio Buffer is not valid!");
     return NS_ERROR_UNEXPECTED;
   }
 
   int64_t timeUs;
@@ -205,54 +231,16 @@ GonkAudioDecoderManager::Output(int64_t 
       GADM_LOG("Decoder failed, err=%d", err);
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
-nsresult
-GonkAudioDecoderManager::Flush()
-{
-  return NS_OK;
-}
-
 void GonkAudioDecoderManager::ReleaseAudioBuffer() {
   if (mAudioBuffer) {
     mDecoder->ReleaseMediaBuffer(mAudioBuffer);
     mAudioBuffer = nullptr;
   }
 }
 
-nsresult
-GonkAudioDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
-{
-  if (mDecoder == nullptr) {
-    GADM_LOG("Decoder is not inited");
-    return NS_ERROR_UNEXPECTED;
-  }
-  if (aSample && mUseAdts) {
-    int8_t frequency_index =
-        mp4_demuxer::Adts::GetFrequencyIndex(mAudioRate);
-    bool rv = mp4_demuxer::Adts::ConvertSample(mAudioChannels,
-                                               frequency_index,
-                                               mAudioProfile,
-                                               aSample);
-    if (!rv) {
-      GADM_LOG("Failed to apply ADTS header");
-      return NS_ERROR_FAILURE;
-    }
-  }
-
-  status_t rv;
-  if (aSample) {
-    const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
-    uint32_t length = aSample->size;
-    rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
-  } else {
-    // Inputted data is null, so it is going to notify decoder EOS
-    rv = mDecoder->Input(0, 0, 0ll, 0);
-  }
-  return rv == OK ? NS_OK : NS_ERROR_UNEXPECTED;
-}
-
 } // namespace mozilla
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
@@ -23,22 +23,24 @@ namespace mozilla {
 class GonkAudioDecoderManager : public GonkDecoderManager {
 typedef android::MediaCodecProxy MediaCodecProxy;
 public:
   GonkAudioDecoderManager(const mp4_demuxer::AudioDecoderConfig& aConfig);
   ~GonkAudioDecoderManager();
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
-  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
-
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
-  virtual nsresult Flush() MOZ_OVERRIDE;
+protected:
+  virtual void PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
+  virtual status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
 private:
 
   nsresult CreateAudioData(int64_t aStreamOffset,
                               AudioData** aOutData);
 
   void ReleaseAudioBuffer();
   // MediaCodedc's wrapper that performs the decoding.
   android::sp<MediaCodecProxy> mDecoder;
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
@@ -19,16 +19,96 @@ PRLogModuleInfo* GetDemuxerLog();
 #else
 #define LOG(...)
 #endif
 
 using namespace android;
 
 namespace mozilla {
 
+GonkDecoderManager::GonkDecoderManager()
+  : mMonitor("GonkDecoderManager")
+  , mInputEOS(false)
+{
+}
+
+nsresult
+GonkDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+
+  // To maintain the order of the MP4Sample, it needs to send the queued samples
+  // to OMX first. And then the current input aSample.
+  // If it fails to input sample to OMX, it needs to add current into queue
+  // for next round.
+  uint32_t len = mQueueSample.Length();
+  status_t rv = OK;
+
+  for (uint32_t i = 0; i < len; i++) {
+    rv = SendSampleToOMX(mQueueSample.ElementAt(0));
+    if (rv != OK) {
+      break;
+    }
+    mQueueSample.RemoveElementAt(0);
+  }
+
+  // Already reaching EOS, do not add any sample to queue.
+  if (mInputEOS) {
+    return NS_OK;
+  }
+
+  // When EOS, aSample will be null and sends this empty MP4Sample to nofity
+  // OMX it reachs EOS.
+  nsAutoPtr<mp4_demuxer::MP4Sample> sample;
+  if (!aSample) {
+    sample = new mp4_demuxer::MP4Sample();
+    mInputEOS = true;
+  }
+
+  // If rv is OK, that means mQueueSample is empty, now try to queue current input
+  // aSample.
+  if (rv == OK) {
+    MOZ_ASSERT(!mQueueSample.Length());
+    mp4_demuxer::MP4Sample* tmp;
+    if (aSample) {
+      tmp = aSample;
+      PerformFormatSpecificProcess(aSample);
+    } else {
+      tmp = sample;
+    }
+    rv = SendSampleToOMX(tmp);
+    if (rv == OK) {
+      return NS_OK;
+    }
+  }
+
+  // Current valid sample can't be sent into OMX, adding the clone one into queue
+  // for next round.
+  if (!sample) {
+      sample = new mp4_demuxer::MP4Sample(*aSample);
+  }
+  mQueueSample.AppendElement(sample);
+
+  // In most cases, EAGAIN or ETIMEOUT safe due to OMX can't process the
+  // filled buffer on time. It should be gone When requeuing sample next time.
+  if (rv == -EAGAIN || rv == -ETIMEDOUT) {
+    return NS_OK;
+  }
+
+  return NS_ERROR_UNEXPECTED;
+}
+
+nsresult
+GonkDecoderManager::Flush()
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+  mQueueSample.Clear();
+  return NS_OK;
+}
+
 GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
                                            MediaTaskQueue* aTaskQueue,
                                            MediaDataDecoderCallback* aCallback)
   : mTaskQueue(aTaskQueue)
   , mCallback(aCallback)
   , mManager(aManager)
   , mSignaledEOS(false)
   , mDrainComplete(false)
@@ -87,30 +167,37 @@ GonkMediaDataDecoder::ProcessDecode(mp4_
 
 void
 GonkMediaDataDecoder::ProcessOutput()
 {
   nsRefPtr<MediaData> output;
   nsresult rv = NS_ERROR_ABORT;
 
   while (!mDrainComplete) {
+    // There are samples in queue, try to send them into decoder when EOS.
+    if (mSignaledEOS && mManager->HasQueuedSample()) {
+      GMDD_LOG("ProcessOutput: drain all input samples");
+      rv = mManager->Input(nullptr);
+    }
     rv = mManager->Output(mLastStreamOffset, output);
     if (rv == NS_OK) {
       mCallback->Output(output);
       continue;
     } else if (rv == NS_ERROR_NOT_AVAILABLE && mSignaledEOS) {
       // Try to get more frames before getting EOS frame
       continue;
     }
     else {
       break;
     }
   }
 
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
+  MOZ_ASSERT_IF(mSignaledEOS, !mManager->HasQueuedSample());
+
+  if (rv == NS_ERROR_NOT_AVAILABLE && !mSignaledEOS) {
     mCallback->InputExhausted();
     return;
   }
   if (rv != NS_OK) {
     NS_WARNING("GonkMediaDataDecoder failed to output data");
     GMDD_LOG("Failed to output data");
     // GonkDecoderManangers report NS_ERROR_ABORT when EOS is reached.
     if (rv == NS_ERROR_ABORT) {
@@ -156,25 +243,26 @@ GonkMediaDataDecoder::Drain()
 }
 
 bool
 GonkMediaDataDecoder::IsWaitingMediaResources() {
   return mDecoder->IsWaitingResources();
 }
 
 bool
-GonkMediaDataDecoder::IsDormantNeeded() {
-
+GonkMediaDataDecoder::IsDormantNeeded()
+{
   return mDecoder.get() ? true : false;
 }
 
 void
 GonkMediaDataDecoder::AllocateMediaResources()
 {
   mManager->AllocateMediaResources();
 }
 
 void
-GonkMediaDataDecoder::ReleaseMediaResources() {
+GonkMediaDataDecoder::ReleaseMediaResources()
+{
   mManager->ReleaseMediaResources();
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
@@ -14,35 +14,68 @@ namespace android {
 class MediaCodecProxy;
 } // namespace android
 
 namespace mozilla {
 
 // Manage the data flow from inputting encoded data and outputting decode data.
 class GonkDecoderManager {
 public:
+  GonkDecoderManager();
+
   virtual ~GonkDecoderManager() {}
 
   // Creates and initializs the GonkDecoder.
   // Returns nullptr on failure.
   virtual android::sp<android::MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) = 0;
 
+  // Add samples into OMX decoder or queue them if decoder is out of input buffer.
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
+
   // Produces decoded output, it blocks until output can be produced or a timeout
   // is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
   // if there's not enough data to produce more output. If this returns a failure
   // code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
   // MP4Reader.
-  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
+  // The overrided class should follow the same behaviour.
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) = 0;
-  virtual nsresult Flush() = 0;
+
+  // Flush the queued sample.
+  // It this function is overrided by subclass, this functino should be called
+  // in the overrided function.
+  virtual nsresult Flush();
+
+  virtual void AllocateMediaResources() {}
+
+  virtual void ReleaseMediaResources() {}
+
+  bool HasQueuedSample() {
+    ReentrantMonitorAutoEnter mon(mMonitor);
+    return mQueueSample.Length();
+  }
 
-  virtual void AllocateMediaResources() {};
+protected:
+  // It performs special operation to MP4 sample, the real action is depended on
+  // the codec type.
+  virtual void PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) {}
+
+  // It sends MP4Sample to OMX layer. It must be overrided by subclass.
+  virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) = 0;
 
-  virtual void ReleaseMediaResources() {};
+  // It protects mQueueSample.
+  ReentrantMonitor mMonitor;
+
+  // An queue with the MP4 samples which are waiting to be sent into OMX.
+  // If an element is an empty MP4Sample, that menas EOS. There should not
+  // any sample be queued after EOS.
+  nsTArray<nsAutoPtr<mp4_demuxer::MP4Sample>> mQueueSample;
+
+  // True when mQueueSample gets an empty MP4Sample.
+  bool mInputEOS;
 };
 
 // Samples are decoded using the GonkDecoder (MediaCodec)
 // created by the GonkDecoderManager. This class implements
 // the higher-level logic that drives mapping the Gonk to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by GonkDecoderManager and the GonkDecoder it creates.
 class GonkMediaDataDecoder : public MediaDataDecoder {
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -44,21 +44,21 @@ typedef android::MediaCodecProxy MediaCo
 
 namespace mozilla {
 enum {
   kNotifyCodecReserved = 'core',
   kNotifyCodecCanceled = 'coca',
 };
 
 GonkVideoDecoderManager::GonkVideoDecoderManager(
-                           mozilla::layers::ImageContainer* aImageContainer,
-		           const mp4_demuxer::VideoDecoderConfig& aConfig)
-  : mImageContainer(aImageContainer)
+  mozilla::layers::ImageContainer* aImageContainer,
+  const mp4_demuxer::VideoDecoderConfig& aConfig)
+  : GonkDecoderManager()
+  , mImageContainer(aImageContainer)
   , mReaderCallback(nullptr)
-  , mMonitor("GonkVideoDecoderManager")
   , mColorConverterBufferSize(0)
   , mNativeWindow(nullptr)
   , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock")
 {
   NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
   MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
   mVideoWidth  = aConfig.display_width;
@@ -119,25 +119,25 @@ GonkVideoDecoderManager::Init(MediaDataD
   }
 
   return mDecoder;
 }
 
 void
 GonkVideoDecoderManager::QueueFrameTimeIn(int64_t aPTS, int64_t aDuration)
 {
-  MonitorAutoLock mon(mMonitor);
+  ReentrantMonitorAutoEnter mon(mMonitor);
   FrameTimeInfo timeInfo = {aPTS, aDuration};
   mFrameTimeInfo.AppendElement(timeInfo);
 }
 
 nsresult
 GonkVideoDecoderManager::QueueFrameTimeOut(int64_t aPTS, int64_t& aDuration)
 {
-  MonitorAutoLock mon(mMonitor);
+  ReentrantMonitorAutoEnter mon(mMonitor);
 
   // Set default to 1 here.
   // During seeking, frames could still in MediaCodec and the mFrameTimeInfo could
   // be cleared before these frames are out from MediaCodec. This is ok because
   // these frames are old frame before seeking.
   aDuration = 1;
   for (uint32_t i = 0; i < mFrameTimeInfo.Length(); i++) {
     const FrameTimeInfo& entry = mFrameTimeInfo.ElementAt(i);
@@ -430,51 +430,51 @@ GonkVideoDecoderManager::Output(int64_t 
 
 void GonkVideoDecoderManager::ReleaseVideoBuffer() {
   if (mVideoBuffer) {
     mDecoder->ReleaseMediaBuffer(mVideoBuffer);
     mVideoBuffer = nullptr;
   }
 }
 
-nsresult
-GonkVideoDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
+status_t
+GonkVideoDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
 {
-  if (mDecoder == nullptr) {
-    GVDM_LOG("Decoder is not inited");
-    return NS_ERROR_UNEXPECTED;
+  // An empty MP4Sample is going to notify EOS to decoder. It doesn't need
+  // to keep PTS and duration.
+  if (aSample->data && aSample->duration && aSample->composition_timestamp) {
+    QueueFrameTimeIn(aSample->composition_timestamp, aSample->duration);
   }
-  status_t rv;
+
+  return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->data),
+                         aSample->size,
+                         aSample->composition_timestamp,
+                         0);
+}
+
+void
+GonkVideoDecoderManager::PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample)
+{
   if (aSample != nullptr) {
     // We must prepare samples in AVC Annex B.
     mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample);
-    // Forward sample data to the decoder.
-
-    QueueFrameTimeIn(aSample->composition_timestamp, aSample->duration);
-
-    const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
-    uint32_t length = aSample->size;
-    rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
   }
-  else {
-    // Inputted data is null, so it is going to notify decoder EOS
-    rv = mDecoder->Input(nullptr, 0, 0ll, 0);
-  }
-  return (rv == OK) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 GonkVideoDecoderManager::Flush()
 {
+  GonkDecoderManager::Flush();
+
   status_t err = mDecoder->flush();
   if (err != OK) {
     return NS_ERROR_FAILURE;
   }
 
-  MonitorAutoLock mon(mMonitor);
+  ReentrantMonitorAutoEnter mon(mMonitor);
   mFrameTimeInfo.Clear();
   return NS_OK;
 }
 
 void
 GonkVideoDecoderManager::AllocateMediaResources()
 {
   mDecoder->RequestMediaResources();
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -40,29 +40,32 @@ typedef mozilla::layers::TextureClient T
 public:
   GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
 		          const mp4_demuxer::VideoDecoderConfig& aConfig);
 
   ~GonkVideoDecoderManager();
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
-  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
-
   virtual nsresult Output(int64_t aStreamOffset,
                           nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
   virtual nsresult Flush() MOZ_OVERRIDE;
 
   virtual void AllocateMediaResources();
 
   virtual void ReleaseMediaResources();
 
   static void RecycleCallback(TextureClient* aClient, void* aClosure);
 
+protected:
+  virtual void PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
+  virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
 private:
   struct FrameInfo
   {
     int32_t mWidth = 0;
     int32_t mHeight = 0;
     int32_t mStride = 0;
     int32_t mSliceHeight = 0;
     int32_t mColorFormat = 0;
@@ -150,22 +153,21 @@ private:
   MediaDataDecoderCallback*  mReaderCallback;
   MediaInfo mInfo;
   android::sp<VideoResourceListener> mVideoListener;
   android::sp<MessageHandler> mHandler;
   android::sp<ALooper> mLooper;
   android::sp<ALooper> mManagerLooper;
   FrameInfo mFrameInfo;
 
-  // It protects mFrameTimeInfo.
-  Monitor mMonitor;
   // Array of FrameTimeInfo whose corresponding frames are sent to OMX.
   // Ideally, it is a FIFO. Input() adds the entry to the end element and
   // CreateVideoData() takes the first entry. However, there are exceptions
   // due to MediaCodec error or seeking.
+  // It is protected by mMonitor.
   nsTArray<FrameTimeInfo> mFrameTimeInfo;
 
   // color converter
   android::I420ColorConverterHelper mColorConverter;
   nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
   size_t mColorConverterBufferSize;
 
   android::sp<android::GonkNativeWindow> mNativeWindow;
--- a/dom/media/gmp-plugin/gmp-fake.cpp
+++ b/dom/media/gmp-plugin/gmp-fake.cpp
@@ -55,16 +55,18 @@
 #include "gmp-test-storage.h"
 
 #if defined(_MSC_VER)
 #define PUBLIC_FUNC __declspec(dllexport)
 #else
 #define PUBLIC_FUNC
 #endif
 
+#define BIG_FRAME 10000
+
 static int g_log_level = 0;
 
 #define GMPLOG(l, x) do { \
         if (l <= g_log_level) { \
         const char *log_string = "unknown"; \
         if ((l >= 0) && (l <= 3)) {               \
         log_string = kLogStrings[l];            \
         } \
@@ -161,17 +163,17 @@ class FakeVideoEncoder : public GMPVideo
     }
     if (!inputImage) {
       GMPLOG (GL_ERROR, "no input image");
       return;
     }
 
     // Now return the encoded data back to the parent.
     GMPVideoFrame* ftmp;
-    GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp);
+    GMPErr err = host_->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
     if (err != GMPNoErr) {
       GMPLOG (GL_ERROR, "Error creating encoded frame");
       return;
     }
 
     GMPVideoEncodedFrame* f = static_cast<GMPVideoEncodedFrame*> (ftmp);
 
     // Encode this in a frame that looks a little bit like H.264.
@@ -187,23 +189,27 @@ class FakeVideoEncoder : public GMPVideo
                              inputImage->AllocatedSize(kGMPYPlane));
     eframe.u_ = AveragePlane(inputImage->Buffer(kGMPUPlane),
                              inputImage->AllocatedSize(kGMPUPlane));
     eframe.v_ = AveragePlane(inputImage->Buffer(kGMPVPlane),
                              inputImage->AllocatedSize(kGMPVPlane));
 
     eframe.timestamp_ = inputImage->Timestamp();
 
-    err = f->CreateEmptyFrame (sizeof(eframe));
+    err = f->CreateEmptyFrame (sizeof(eframe) +
+                               (frame_type  == kGMPKeyFrame ? sizeof(uint32_t) + BIG_FRAME : 0));
     if (err != GMPNoErr) {
       GMPLOG (GL_ERROR, "Error allocating frame data");
       f->Destroy();
       return;
     }
     memcpy(f->Buffer(), &eframe, sizeof(eframe));
+    if (frame_type  == kGMPKeyFrame) {
+      *((uint32_t*) f->Buffer() + sizeof(eframe)) = BIG_FRAME;
+    }
 
     f->SetEncodedWidth (inputImage->Width());
     f->SetEncodedHeight (inputImage->Height());
     f->SetTimeStamp (inputImage->Timestamp());
     f->SetFrameType (frame_type);
     f->SetCompleteFrame (true);
     f->SetBufferType(GMP_BufferLength32);
 
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -535,16 +535,22 @@ MediaSource::Dump(const char* aPath)
   PR_MkDir(buf, 0700);
 
   if (mSourceBuffers) {
     mSourceBuffers->Dump(buf);
   }
 }
 #endif
 
+void
+MediaSource::GetMozDebugReaderData(nsAString& aString)
+{
+  mDecoder->GetMozDebugReaderData(aString);
+}
+
 nsPIDOMWindow*
 MediaSource::GetParentObject() const
 {
   return GetOwner();
 }
 
 JSObject*
 MediaSource::WrapObject(JSContext* aCx)
--- a/dom/media/mediasource/MediaSource.h
+++ b/dom/media/mediasource/MediaSource.h
@@ -109,16 +109,20 @@ public:
   void QueueInitializationEvent();
 
 #if defined(DEBUG)
   // Dump the contents of each SourceBuffer to a series of files under aPath.
   // aPath must exist.  Debug only, invoke from your favourite debugger.
   void Dump(const char* aPath);
 #endif
 
+  // Returns a string describing the state of the MediaSource internal
+  // buffered data. Used for debugging purposes.
+  void GetMozDebugReaderData(nsAString& aString);
+
 private:
   // MediaSourceDecoder uses DurationChange to set the duration
   // without hitting the checks in SetDuration.
   friend class mozilla::MediaSourceDecoder;
   // SourceBuffer uses SetDuration
   friend class mozilla::dom::SourceBuffer;
 
   ~MediaSource();
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -285,16 +285,22 @@ MediaSourceDecoder::NotifyTimeRangesChan
 
 void
 MediaSourceDecoder::PrepareReaderInitialization()
 {
   MOZ_ASSERT(mReader);
   mReader->PrepareInitialization();
 }
 
+void
+MediaSourceDecoder::GetMozDebugReaderData(nsAString& aString)
+{
+  mReader->GetMozDebugReaderData(aString);
+}
+
 #ifdef MOZ_EME
 nsresult
 MediaSourceDecoder::SetCDMProxy(CDMProxy* aProxy)
 {
   nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mReader->SetCDMProxy(aProxy);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/media/mediasource/MediaSourceDecoder.h
+++ b/dom/media/mediasource/MediaSourceDecoder.h
@@ -74,16 +74,20 @@ public:
 #endif
 
   MediaSourceReader* GetReader() { return mReader; }
 
   // Returns true if aReader is a currently active audio or video
   // reader in this decoders MediaSourceReader.
   bool IsActiveReader(MediaDecoderReader* aReader);
 
+  // Returns a string describing the state of the MediaSource internal
+  // buffered data. Used for debugging purposes.
+  void GetMozDebugReaderData(nsAString& aString);
+
 private:
   void DoSetMediaSourceDuration(double aDuration);
   void ScheduleDurationChange(double aOldDuration,
                               double aNewDuration,
                               MSRangeRemovalAction aAction);
 
   // The owning MediaSource holds a strong reference to this decoder, and
   // calls Attach/DetachMediaSource on this decoder to set and clear
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -8,16 +8,17 @@
 #include "prlog.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "DecoderTraits.h"
 #include "MediaDecoderOwner.h"
 #include "MediaSourceDecoder.h"
 #include "MediaSourceUtils.h"
 #include "SourceBufferDecoder.h"
 #include "TrackBuffer.h"
+#include "nsPrintfCString.h"
 
 #ifdef MOZ_FMP4
 #include "SharedDecoderManager.h"
 #include "MP4Decoder.h"
 #include "MP4Reader.h"
 #endif
 
 #ifdef PR_LOGGING
@@ -45,19 +46,17 @@ using mozilla::dom::TimeRanges;
 namespace mozilla {
 
 MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
   : MediaDecoderReader(aDecoder)
   , mLastAudioTime(0)
   , mLastVideoTime(0)
   , mPendingSeekTime(-1)
   , mWaitingForSeekData(false)
-  , mAudioIsSeeking(false)
-  , mVideoIsSeeking(false)
-  , mTimeThreshold(-1)
+  , mTimeThreshold(0)
   , mDropAudioBeforeThreshold(false)
   , mDropVideoBeforeThreshold(false)
   , mEnded(false)
   , mMediaSourceDuration(0)
   , mHasEssentialTrackBuffers(false)
 #ifdef MOZ_FMP4
   , mSharedDecoderManager(new SharedDecoderManager())
 #endif
@@ -114,79 +113,74 @@ MediaSourceReader::RequestAudioData()
 {
   nsRefPtr<AudioDataPromise> p = mAudioPromise.Ensure(__func__);
   MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData", this);
   if (!mAudioReader) {
     MSE_DEBUG("MediaSourceReader(%p)::RequestAudioData called with no audio reader", this);
     mAudioPromise.Reject(DECODE_ERROR, __func__);
     return p;
   }
-  if (mAudioIsSeeking) {
+  if (IsSeeking()) {
     MSE_DEBUG("MediaSourceReader(%p)::RequestAudioData called mid-seek. Rejecting.", this);
     mAudioPromise.Reject(CANCELED, __func__);
     return p;
   }
+  MOZ_RELEASE_ASSERT(!mAudioSeekRequest.Exists());
+
   SwitchReaderResult ret = SwitchAudioReader(mLastAudioTime);
   switch (ret) {
     case READER_NEW:
-      mAudioReader->Seek(mLastAudioTime, 0)
-                  ->Then(GetTaskQueue(), __func__, this,
-                         &MediaSourceReader::RequestAudioDataComplete,
-                         &MediaSourceReader::RequestAudioDataFailed);
+      mAudioSeekRequest.Begin(mAudioReader->Seek(mLastAudioTime, 0)
+                              ->RefableThen(GetTaskQueue(), __func__, this,
+                                            &MediaSourceReader::CompleteAudioSeekAndDoRequest,
+                                            &MediaSourceReader::CompleteAudioSeekAndRejectPromise));
       break;
     case READER_ERROR:
       if (mLastAudioTime) {
         CheckForWaitOrEndOfStream(MediaData::AUDIO_DATA, mLastAudioTime);
         break;
       }
       // Fallback to using current reader
     default:
-      RequestAudioDataComplete(0);
+      DoAudioRequest();
       break;
   }
   return p;
 }
 
-void
-MediaSourceReader::RequestAudioDataComplete(int64_t aTime)
+void MediaSourceReader::DoAudioRequest()
 {
-  mAudioReader->RequestAudioData()->Then(GetTaskQueue(), __func__, this,
-                                         &MediaSourceReader::OnAudioDecoded,
-                                         &MediaSourceReader::OnAudioNotDecoded);
-}
-
-void
-MediaSourceReader::RequestAudioDataFailed(nsresult aResult)
-{
-  OnAudioNotDecoded(DECODE_ERROR);
+  mAudioRequest.Begin(mAudioReader->RequestAudioData()
+                      ->RefableThen(GetTaskQueue(), __func__, this,
+                                    &MediaSourceReader::OnAudioDecoded,
+                                    &MediaSourceReader::OnAudioNotDecoded));
 }
 
 void
 MediaSourceReader::OnAudioDecoded(AudioData* aSample)
 {
+  MOZ_RELEASE_ASSERT(!IsSeeking());
+  mAudioRequest.Complete();
+
   MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
              this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
   if (mDropAudioBeforeThreshold) {
     if (aSample->mTime < mTimeThreshold) {
       MSE_DEBUG("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld < mTimeThreshold=%lld",
                 this, aSample->mTime, mTimeThreshold);
-      mAudioReader->RequestAudioData()->Then(GetTaskQueue(), __func__, this,
-                                             &MediaSourceReader::OnAudioDecoded,
-                                             &MediaSourceReader::OnAudioNotDecoded);
+      mAudioRequest.Begin(mAudioReader->RequestAudioData()
+                          ->RefableThen(GetTaskQueue(), __func__, this,
+                                        &MediaSourceReader::OnAudioDecoded,
+                                        &MediaSourceReader::OnAudioNotDecoded));
       return;
     }
     mDropAudioBeforeThreshold = false;
   }
 
-  // Any OnAudioDecoded callbacks received while mAudioIsSeeking must be not
-  // update our last used timestamp, as these are emitted by the reader we're
-  // switching away from.
-  if (!mAudioIsSeeking) {
-    mLastAudioTime = aSample->mTime + aSample->mDuration;
-  }
+  mLastAudioTime = aSample->mTime + aSample->mDuration;
 
   mAudioPromise.Resolve(aSample, __func__);
 }
 
 // Find the closest approximation to the end time for this stream.
 // mLast{Audio,Video}Time differs from the actual end time because of
 // Bug 1065207 - the duration of a WebM fragment is an estimate not the
 // actual duration. In the case of audio time an example of where they
@@ -210,16 +204,19 @@ AdjustEndTime(int64_t* aEndTime, MediaDe
       *aEndTime = std::max(*aEndTime, end);
     }
   }
 }
 
 void
 MediaSourceReader::OnAudioNotDecoded(NotDecodedReason aReason)
 {
+  MOZ_RELEASE_ASSERT(!IsSeeking());
+  mAudioRequest.Complete();
+
   MSE_DEBUG("MediaSourceReader(%p)::OnAudioNotDecoded aReason=%u IsEnded: %d", this, aReason, IsEnded());
   if (aReason == DECODE_ERROR || aReason == CANCELED) {
     mAudioPromise.Reject(aReason, __func__);
     return;
   }
 
   // End of stream. Force switching past this stream to another reader by
   // switching to the end of the buffered range.
@@ -227,20 +224,20 @@ MediaSourceReader::OnAudioNotDecoded(Not
   if (mAudioReader) {
     AdjustEndTime(&mLastAudioTime, mAudioReader);
   }
 
   // See if we can find a different reader that can pick up where we left off. We use the
   // EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
   // 1065207.
   if (SwitchAudioReader(mLastAudioTime, EOS_FUZZ_US) == READER_NEW) {
-    mAudioReader->Seek(mLastAudioTime, 0)
-                ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::RequestAudioDataComplete,
-                       &MediaSourceReader::RequestAudioDataFailed);
+    mAudioSeekRequest.Begin(mAudioReader->Seek(mLastAudioTime, 0)
+                            ->RefableThen(GetTaskQueue(), __func__, this,
+                                          &MediaSourceReader::CompleteAudioSeekAndDoRequest,
+                                          &MediaSourceReader::CompleteAudioSeekAndRejectPromise));
     return;
   }
 
   CheckForWaitOrEndOfStream(MediaData::AUDIO_DATA, mLastAudioTime);
 }
 
 
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
@@ -254,89 +251,84 @@ MediaSourceReader::RequestVideoData(bool
     mVideoPromise.Reject(DECODE_ERROR, __func__);
     return p;
   }
   if (aSkipToNextKeyframe) {
     mTimeThreshold = aTimeThreshold;
     mDropAudioBeforeThreshold = true;
     mDropVideoBeforeThreshold = true;
   }
-  if (mVideoIsSeeking) {
+  if (IsSeeking()) {
     MSE_DEBUG("MediaSourceReader(%p)::RequestVideoData called mid-seek. Rejecting.", this);
     mVideoPromise.Reject(CANCELED, __func__);
     return p;
   }
+  MOZ_RELEASE_ASSERT(!mVideoSeekRequest.Exists());
+
   SwitchReaderResult ret = SwitchVideoReader(mLastVideoTime);
   switch (ret) {
     case READER_NEW:
-      mVideoReader->Seek(mLastVideoTime, 0)
-                  ->Then(GetTaskQueue(), __func__, this,
-                         &MediaSourceReader::RequestVideoDataComplete,
-                         &MediaSourceReader::RequestVideoDataFailed);
+      mVideoSeekRequest.Begin(mVideoReader->Seek(mLastVideoTime, 0)
+                             ->RefableThen(GetTaskQueue(), __func__, this,
+                                           &MediaSourceReader::CompleteVideoSeekAndDoRequest,
+                                           &MediaSourceReader::CompleteVideoSeekAndRejectPromise));
       break;
     case READER_ERROR:
       if (mLastVideoTime) {
         CheckForWaitOrEndOfStream(MediaData::VIDEO_DATA, mLastVideoTime);
         break;
       }
       // Fallback to using current reader.
     default:
-      mVideoReader->RequestVideoData(aSkipToNextKeyframe, aTimeThreshold)
-                  ->Then(GetTaskQueue(), __func__, this,
-                         &MediaSourceReader::OnVideoDecoded, &MediaSourceReader::OnVideoNotDecoded);
+      DoVideoRequest();
       break;
   }
 
   return p;
 }
 
 void
-MediaSourceReader::RequestVideoDataComplete(int64_t aTime)
+MediaSourceReader::DoVideoRequest()
 {
-  mVideoReader->RequestVideoData(false, 0)
-              ->Then(GetTaskQueue(), __func__, this,
-                     &MediaSourceReader::OnVideoDecoded, &MediaSourceReader::OnVideoNotDecoded);
-}
-
-void
-MediaSourceReader::RequestVideoDataFailed(nsresult aResult)
-{
-  OnVideoNotDecoded(DECODE_ERROR);
+  mVideoRequest.Begin(mVideoReader->RequestVideoData(mDropVideoBeforeThreshold, mTimeThreshold)
+                      ->RefableThen(GetTaskQueue(), __func__, this,
+                                    &MediaSourceReader::OnVideoDecoded,
+                                    &MediaSourceReader::OnVideoNotDecoded));
 }
 
 void
 MediaSourceReader::OnVideoDecoded(VideoData* aSample)
 {
+  MOZ_RELEASE_ASSERT(!IsSeeking());
+  mVideoRequest.Complete();
+
   MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
              this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
   if (mDropVideoBeforeThreshold) {
     if (aSample->mTime < mTimeThreshold) {
       MSE_DEBUG("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld < mTimeThreshold=%lld",
                 this, aSample->mTime, mTimeThreshold);
-      mVideoReader->RequestVideoData(false, 0)->Then(GetTaskQueue(), __func__, this,
-                                                     &MediaSourceReader::OnVideoDecoded,
-                                                     &MediaSourceReader::OnVideoNotDecoded);
+      DoVideoRequest();
       return;
     }
     mDropVideoBeforeThreshold = false;
+    mTimeThreshold = 0;
   }
 
-  // Any OnVideoDecoded callbacks received while mVideoIsSeeking must be not
-  // update our last used timestamp, as these are emitted by the reader we're
-  // switching away from.
-  if (!mVideoIsSeeking) {
-    mLastVideoTime = aSample->mTime + aSample->mDuration;
-  }
+  mLastVideoTime = aSample->mTime + aSample->mDuration;
 
   mVideoPromise.Resolve(aSample, __func__);
 }
 
 void
 MediaSourceReader::OnVideoNotDecoded(NotDecodedReason aReason)
 {
+  MOZ_RELEASE_ASSERT(!IsSeeking());
+  mVideoRequest.Complete();
+
   MSE_DEBUG("MediaSourceReader(%p)::OnVideoNotDecoded aReason=%u IsEnded: %d", this, aReason, IsEnded());
   if (aReason == DECODE_ERROR || aReason == CANCELED) {
     mVideoPromise.Reject(aReason, __func__);
     return;
   }
 
   // End of stream. Force switching past this stream to another reader by
   // switching to the end of the buffered range.
@@ -344,20 +336,20 @@ MediaSourceReader::OnVideoNotDecoded(Not
   if (mVideoReader) {
     AdjustEndTime(&mLastVideoTime, mVideoReader);
   }
 
   // See if we can find a different reader that can pick up where we left off. We use the
   // EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
   // 1065207.
   if (SwitchVideoReader(mLastVideoTime, EOS_FUZZ_US) == READER_NEW) {
-    mVideoReader->Seek(mLastVideoTime, 0)
-                ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::RequestVideoDataComplete,
-                       &MediaSourceReader::RequestVideoDataFailed);
+    mVideoSeekRequest.Begin(mVideoReader->Seek(mLastVideoTime, 0)
+                           ->RefableThen(GetTaskQueue(), __func__, this,
+                                         &MediaSourceReader::CompleteVideoSeekAndDoRequest,
+                                         &MediaSourceReader::CompleteVideoSeekAndRejectPromise));
     return;
   }
 
   CheckForWaitOrEndOfStream(MediaData::VIDEO_DATA, mLastVideoTime);
 }
 
 void
 MediaSourceReader::CheckForWaitOrEndOfStream(MediaData::Type aType, int64_t aTime)
@@ -670,16 +662,30 @@ MediaSourceReader::Seek(int64_t aTime, i
   MOZ_ASSERT(mSeekPromise.IsEmpty());
   nsRefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__);
 
   if (IsShutdown()) {
     mSeekPromise.Reject(NS_ERROR_FAILURE, __func__);
     return p;
   }
 
+  // Any previous requests we've been waiting on are now unwanted.
+  mAudioRequest.DisconnectIfExists();
+  mVideoRequest.DisconnectIfExists();
+
+  // Additionally, reject any outstanding promises _we_ made that we might have
+  // been waiting on the above to fulfill.
+  mAudioPromise.RejectIfExists(CANCELED, __func__);
+  mVideoPromise.RejectIfExists(CANCELED, __func__);
+
+  // Finally, if we were midway seeking a new reader to find a sample, abandon
+  // that too.
+  mAudioSeekRequest.DisconnectIfExists();
+  mVideoSeekRequest.DisconnectIfExists();
+
   // Store pending seek target in case the track buffers don't contain
   // the desired time and we delay doing the seek.
   mPendingSeekTime = aTime;
 
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mWaitingForSeekData = true;
   }
@@ -688,79 +694,74 @@ MediaSourceReader::Seek(int64_t aTime, i
   return p;
 }
 
 void
 MediaSourceReader::CancelSeek()
 {
   MOZ_ASSERT(OnDecodeThread());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  if (mWaitingForSeekData) {
-    mSeekPromise.Reject(NS_OK, __func__);
-    mWaitingForSeekData = false;
-    mPendingSeekTime = -1;
-  } else if (mVideoIsSeeking) {
-    // NB: Currently all readers have sync Seeks(), so this is a no-op.
+  mWaitingForSeekData = false;
+  mPendingSeekTime = -1;
+  if (mAudioReader) {
+    mAudioSeekRequest.DisconnectIfExists();
+    mAudioReader->CancelSeek();
+  }
+  if (mVideoReader) {
+    mVideoSeekRequest.DisconnectIfExists();
     mVideoReader->CancelSeek();
-  } else if (mAudioIsSeeking) {
-    // NB: Currently all readers have sync Seeks(), so this is a no-op.
-    mAudioReader->CancelSeek();
-  } else {
-    MOZ_ASSERT(mSeekPromise.IsEmpty());
   }
+  mSeekPromise.RejectIfExists(NS_OK, __func__);
 }
 
 void
 MediaSourceReader::OnVideoSeekCompleted(int64_t aTime)
 {
-  mPendingSeekTime = aTime;
-  MOZ_ASSERT(mVideoIsSeeking);
-  MOZ_ASSERT(!mAudioIsSeeking);
-  mVideoIsSeeking = false;
+  mVideoSeekRequest.Complete();
 
   if (mAudioTrack) {
-    mAudioIsSeeking = true;
+    mPendingSeekTime = aTime;
+    DoAudioSeek();
+  } else {
+    mPendingSeekTime = -1;
+    mSeekPromise.Resolve(aTime, __func__);
+  }
+}
+
+void
+MediaSourceReader::OnVideoSeekFailed(nsresult aResult)
+{
+  mVideoSeekRequest.Complete();
+  mPendingSeekTime = -1;
+  mSeekPromise.Reject(aResult, __func__);
+}
+
+void
+MediaSourceReader::DoAudioSeek()
+{
     SwitchAudioReader(mPendingSeekTime);
-    mAudioReader->Seek(mPendingSeekTime, 0)
-                ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::OnAudioSeekCompleted,
-                       &MediaSourceReader::OnSeekFailed);
-    MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p", this, mAudioReader.get());
-    return;
-  }
-  mSeekPromise.Resolve(mPendingSeekTime, __func__);
+    mAudioSeekRequest.Begin(mAudioReader->Seek(mPendingSeekTime, 0)
+                           ->RefableThen(GetTaskQueue(), __func__, this,
+                                         &MediaSourceReader::OnAudioSeekCompleted,
+                                         &MediaSourceReader::OnAudioSeekFailed));
+    MSE_DEBUG("MediaSourceReader(%p)::DoAudioSeek reader=%p", this, mAudioReader.get());
 }
 
 void
 MediaSourceReader::OnAudioSeekCompleted(int64_t aTime)
 {
-  mPendingSeekTime = aTime;
-  MOZ_ASSERT(mAudioIsSeeking);
-  MOZ_ASSERT(!mVideoIsSeeking);
-  mAudioIsSeeking = false;
-
-  mSeekPromise.Resolve(mPendingSeekTime, __func__);
+  mAudioSeekRequest.Complete();
   mPendingSeekTime = -1;
+  mSeekPromise.Resolve(aTime, __func__);
 }
 
 void
-MediaSourceReader::OnSeekFailed(nsresult aResult)
+MediaSourceReader::OnAudioSeekFailed(nsresult aResult)
 {
-  MOZ_ASSERT(mVideoIsSeeking || mAudioIsSeeking);
-
-  if (mVideoIsSeeking) {
-    MOZ_ASSERT(!mAudioIsSeeking);
-    mVideoIsSeeking = false;
-  }
-
-  if (mAudioIsSeeking) {
-    MOZ_ASSERT(!mVideoIsSeeking);
-    mAudioIsSeeking = false;
-  }
-
+  mAudioSeekRequest.Complete();
   mPendingSeekTime = -1;
   mSeekPromise.Reject(aResult, __func__);
 }
 
 void
 MediaSourceReader::AttemptSeek()
 {
   // Make sure we don't hold the monitor while calling into the reader
@@ -778,28 +779,35 @@ MediaSourceReader::AttemptSeek()
     mTrackBuffers[i]->ResetDecode();
   }
 
   // Decoding discontinuity upon seek, reset last times to seek target.
   mLastAudioTime = mPendingSeekTime;
   mLastVideoTime = mPendingSeekTime;
 
   if (mVideoTrack) {
-    mVideoIsSeeking = true;
-    SwitchVideoReader(mPendingSeekTime);
-    mVideoReader->Seek(mPendingSeekTime, 0)
-                ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::OnVideoSeekCompleted,
-                       &MediaSourceReader::OnSeekFailed);
-    MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p", this, mVideoReader.get());
+    DoVideoSeek();
+  } else if (mAudioTrack) {
+    DoAudioSeek();
   } else {
-    OnVideoSeekCompleted(mPendingSeekTime);
+    MOZ_CRASH();
   }
 }
 
+void
+MediaSourceReader::DoVideoSeek()
+{
+  SwitchVideoReader(mPendingSeekTime);
+  mVideoSeekRequest.Begin(mVideoReader->Seek(mPendingSeekTime, 0)
+                          ->RefableThen(GetTaskQueue(), __func__, this,
+                                        &MediaSourceReader::OnVideoSeekCompleted,
+                                        &MediaSourceReader::OnVideoSeekFailed));
+  MSE_DEBUG("MediaSourceReader(%p)::DoVideoSeek reader=%p", this, mVideoReader.get());
+}
+
 nsresult
 MediaSourceReader::GetBuffered(dom::TimeRanges* aBuffered)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   MOZ_ASSERT(aBuffered->Length() == 0);
   if (mTrackBuffers.IsEmpty()) {
     return NS_OK;
   }
@@ -844,21 +852,21 @@ MediaSourceReader::WaitForData(MediaData
   return p;
 }
 
 void
 MediaSourceReader::MaybeNotifyHaveData()
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   bool haveAudio = false, haveVideo = false;
-  if (!mAudioIsSeeking && mAudioTrack && HaveData(mLastAudioTime, MediaData::AUDIO_DATA)) {
+  if (!IsSeeking() && mAudioTrack && HaveData(mLastAudioTime, MediaData::AUDIO_DATA)) {
     haveAudio = true;
     WaitPromise(MediaData::AUDIO_DATA).ResolveIfExists(MediaData::AUDIO_DATA, __func__);
   }
-  if (!mVideoIsSeeking && mVideoTrack && HaveData(mLastVideoTime, MediaData::VIDEO_DATA)) {
+  if (!IsSeeking() && mVideoTrack && HaveData(mLastVideoTime, MediaData::VIDEO_DATA)) {
     haveVideo = true;
     WaitPromise(MediaData::VIDEO_DATA).ResolveIfExists(MediaData::VIDEO_DATA, __func__);
   }
   MSE_DEBUG("MediaSourceReader(%p)::MaybeNotifyHaveData haveAudio=%d, haveVideo=%d", this,
             haveAudio, haveVideo);
 }
 
 nsresult
@@ -963,16 +971,52 @@ MediaSourceReader::IsNearEnd(int64_t aTi
 
 void
 MediaSourceReader::SetMediaSourceDuration(double aDuration)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   mMediaSourceDuration = aDuration;
 }
 
+void
+MediaSourceReader::GetMozDebugReaderData(nsAString& aString)
+{
+  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+  nsAutoCString result;
+  result += nsPrintfCString("Dumping data for reader %p:\n", this);
+  if (mAudioTrack) {
+    result += nsPrintfCString("\tDumping Audio Track Decoders: - mLastAudioTime: %f\n", double(mLastAudioTime) / USECS_PER_S);
+    for (int32_t i = mAudioTrack->Decoders().Length() - 1; i >= 0; --i) {
+      nsRefPtr<MediaDecoderReader> newReader = mAudioTrack->Decoders()[i]->GetReader();
+
+      nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
+      mAudioTrack->Decoders()[i]->GetBuffered(ranges);
+      result += nsPrintfCString("\t\tReader %d: %p ranges=%s active=%s size=%lld\n",
+                                i, newReader.get(), DumpTimeRanges(ranges).get(),
+                                newReader.get() == mAudioReader.get() ? "true" : "false",
+                                mAudioTrack->Decoders()[i]->GetResource()->GetSize());
+    }
+  }
+
+  if (mVideoTrack) {
+    result += nsPrintfCString("\tDumping Video Track Decoders - mLastVideoTime: %f\n", double(mLastVideoTime) / USECS_PER_S);
+    for (int32_t i = mVideoTrack->Decoders().Length() - 1; i >= 0; --i) {
+      nsRefPtr<MediaDecoderReader> newReader = mVideoTrack->Decoders()[i]->GetReader();
+
+      nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
+      mVideoTrack->Decoders()[i]->GetBuffered(ranges);
+      result += nsPrintfCString("\t\tReader %d: %p ranges=%s active=%s size=%lld\n",
+                                i, newReader.get(), DumpTimeRanges(ranges).get(),
+                                newReader.get() == mVideoReader.get() ? "true" : "false",
+                                mVideoTrack->Decoders()[i]->GetResource()->GetSize());
+    }
+  }
+  aString += NS_ConvertUTF8toUTF16(result);
+}
+
 #ifdef MOZ_EME
 nsresult
 MediaSourceReader::SetCDMProxy(CDMProxy* aProxy)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
   mCDMProxy = aProxy;
   for (size_t i = 0; i < mTrackBuffers.Length(); i++) {
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -56,19 +56,22 @@ public:
   virtual bool IsDormantNeeded() MOZ_OVERRIDE;
   virtual void ReleaseMediaResources() MOZ_OVERRIDE;
 
   void OnAudioDecoded(AudioData* aSample);
   void OnAudioNotDecoded(NotDecodedReason aReason);
   void OnVideoDecoded(VideoData* aSample);
   void OnVideoNotDecoded(NotDecodedReason aReason);
 
+  void DoVideoSeek();
+  void DoAudioSeek();
   void OnVideoSeekCompleted(int64_t aTime);
+  void OnVideoSeekFailed(nsresult aResult);
   void OnAudioSeekCompleted(int64_t aTime);
-  void OnSeekFailed(nsresult aResult);
+  void OnAudioSeekFailed(nsresult aResult);
 
   virtual bool IsWaitForDataSupported() MOZ_OVERRIDE { return true; }
   virtual nsRefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) MOZ_OVERRIDE;
   void MaybeNotifyHaveData();
 
   bool HasVideo() MOZ_OVERRIDE
   {
     return mInfo.HasVideo();
@@ -141,53 +144,85 @@ public:
   virtual bool IsAsync() const MOZ_OVERRIDE {
     return (!mAudioReader || mAudioReader->IsAsync()) &&
            (!mVideoReader || mVideoReader->IsAsync());
   }
 
   // Returns true if aReader is a currently active audio or video
   bool IsActiveReader(MediaDecoderReader* aReader);
 
+  // Returns a string describing the state of the MediaSource internal
+  // buffered data. Used for debugging purposes.
+  void GetMozDebugReaderData(nsAString& aString);
+
 private:
   // Switch the current audio/video reader to the reader that
   // contains aTarget (or up to aError after target). Both
   // aTarget and aError are in microseconds.
   enum SwitchReaderResult {
     READER_ERROR = -1,
     READER_EXISTING = 0,
     READER_NEW = 1,
   };
   SwitchReaderResult SwitchAudioReader(int64_t aTarget, int64_t aError = 0);
   SwitchReaderResult SwitchVideoReader(int64_t aTarget, int64_t aError = 0);
-  void RequestAudioDataComplete(int64_t aTime);
-  void RequestAudioDataFailed(nsresult aResult);
-  void RequestVideoDataComplete(int64_t aTime);
-  void RequestVideoDataFailed(nsresult aResult);
+
+  void DoAudioRequest();
+  void DoVideoRequest();
+
+  void CompleteAudioSeekAndDoRequest()
+  {
+    mAudioSeekRequest.Complete();
+    DoAudioRequest();
+  }
+
+  void CompleteVideoSeekAndDoRequest()
+  {
+    mVideoSeekRequest.Complete();
+    DoVideoRequest();
+  }
+
+  void CompleteAudioSeekAndRejectPromise()
+  {
+    mAudioSeekRequest.Complete();
+    mAudioPromise.Reject(DECODE_ERROR, __func__);
+  }
+
+  void CompleteVideoSeekAndRejectPromise()
+  {
+    mVideoSeekRequest.Complete();
+    mVideoPromise.Reject(DECODE_ERROR, __func__);
+  }
+
   // Will reject the MediaPromise with END_OF_STREAM if mediasource has ended
   // or with WAIT_FOR_DATA otherwise.
   void CheckForWaitOrEndOfStream(MediaData::Type aType, int64_t aTime /* microseconds */);
 
   // Return a reader from the set available in aTrackDecoders that has data
   // available in the range requested by aTarget.
   already_AddRefed<MediaDecoderReader> SelectReader(int64_t aTarget,
                                                     int64_t aError,
                                                     const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
   bool HaveData(int64_t aTarget, MediaData::Type aType);
 
   void AttemptSeek();
+  bool IsSeeking() { return mPendingSeekTime != -1; }
 
   nsRefPtr<MediaDecoderReader> mAudioReader;
   nsRefPtr<MediaDecoderReader> mVideoReader;
 
   nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mShutdownTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mEssentialTrackBuffers;
   nsRefPtr<TrackBuffer> mAudioTrack;
   nsRefPtr<TrackBuffer> mVideoTrack;
 
+  MediaPromiseConsumerHolder<AudioDataPromise> mAudioRequest;
+  MediaPromiseConsumerHolder<VideoDataPromise> mVideoRequest;
+
   MediaPromiseHolder<AudioDataPromise> mAudioPromise;
   MediaPromiseHolder<VideoDataPromise> mVideoPromise;
 
   MediaPromiseHolder<WaitForDataPromise> mAudioWaitPromise;
   MediaPromiseHolder<WaitForDataPromise> mVideoWaitPromise;
   MediaPromiseHolder<WaitForDataPromise>& WaitPromise(MediaData::Type aType)
   {
     return aType == MediaData::AUDIO_DATA ? mAudioWaitPromise : mVideoWaitPromise;
@@ -196,23 +231,24 @@ private:
 #ifdef MOZ_EME
   nsRefPtr<CDMProxy> mCDMProxy;
 #endif
 
   // These are read and written on the decode task queue threads.
   int64_t mLastAudioTime;
   int64_t mLastVideoTime;
 
+  MediaPromiseConsumerHolder<SeekPromise> mAudioSeekRequest;
+  MediaPromiseConsumerHolder<SeekPromise> mVideoSeekRequest;
+  MediaPromiseHolder<SeekPromise> mSeekPromise;
+
   // Temporary seek information while we wait for the data
   // to be added to the track buffer.
-  MediaPromiseHolder<SeekPromise> mSeekPromise;
   int64_t mPendingSeekTime;
   bool mWaitingForSeekData;
-  bool mAudioIsSeeking;
-  bool mVideoIsSeeking;
 
   int64_t mTimeThreshold;
   bool mDropAudioBeforeThreshold;
   bool mDropVideoBeforeThreshold;
 
   bool mEnded;
   double mMediaSourceDuration;
 
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -176,17 +176,16 @@ MediaEngineDefaultVideoSource::Stop(Sour
   mTimer = nullptr;
 
   aSource->EndTrack(aID);
   if (mHasFakeTracks) {
     for (int i = 0; i < kFakeVideoTrackCount; ++i) {
       aSource->EndTrack(kTrackCount + i);
     }
   }
-  aSource->Finish();
 
   mState = kStopped;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
 {
@@ -433,17 +432,16 @@ MediaEngineDefaultAudioSource::Stop(Sour
   mTimer = nullptr;
 
   aSource->EndTrack(aID);
   if (mHasFakeTracks) {
     for (int i = 0; i < kFakeAudioTrackCount; ++i) {
       aSource->EndTrack(kTrackCount + kFakeVideoTrackCount+i);
     }
   }
-  aSource->Finish();
 
   mState = kStopped;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaEngineDefaultAudioSource::Notify(nsITimer* aTimer)
 {
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -35,17 +35,16 @@
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
 #include "webrtc/voice_engine/include/voe_hardware.h"
 #include "webrtc/voice_engine/include/voe_network.h"
 #include "webrtc/voice_engine/include/voe_audio_processing.h"
 #include "webrtc/voice_engine/include/voe_volume_control.h"
 #include "webrtc/voice_engine/include/voe_external_media.h"
 #include "webrtc/voice_engine/include/voe_audio_processing.h"
-#include "webrtc/voice_engine/include/voe_call_report.h"
 
 // Video Engine
 // conflicts with #include of scoped_ptr.h
 #undef FF
 #include "webrtc/video_engine/include/vie_base.h"
 #include "webrtc/video_engine/include/vie_codec.h"
 #include "webrtc/video_engine/include/vie_render.h"
 #include "webrtc/video_engine/include/vie_capture.h"
@@ -64,16 +63,17 @@ class MediaEngineWebRTCVideoSource : pub
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // ViEExternalRenderer.
   virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams) MOZ_OVERRIDE;
   virtual int DeliverFrame(unsigned char* buffer,
                            int size,
                            uint32_t time_stamp,
+                           int64_t ntp_time_ms,
                            int64_t render_time,
                            void *handle) MOZ_OVERRIDE;
   /**
    * Does DeliverFrame() support a null buffer and non-null handle
    * (video texture)?
    * XXX Investigate!  Especially for Android/B2G
    */
   virtual bool IsTextureSupported() MOZ_OVERRIDE { return false; }
@@ -214,17 +214,16 @@ private:
   void Init();
   void Shutdown();
 
   webrtc::VoiceEngine* mVoiceEngine;
   ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
   ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender;
   ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
   ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
-  ScopedCustomReleasePtr<webrtc::VoECallReport> mVoECallReport;
 
   // mMonitor protects mSources[] access/changes, and transitions of mState
   // from kStarted to kStopped (which are combined with EndTrack()).
   // mSources[] is accessed from webrtc threads.
   Monitor mMonitor;
   nsTArray<SourceMediaStream*> mSources; // When this goes empty, we shut down HW
   nsCOMPtr<nsIThread> mThread;
   int mCapIndex;
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -431,21 +431,16 @@ MediaEngineWebRTCAudioSource::Init()
     return;
   }
 
   mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine);
   if (!mVoEProcessing) {
     return;
   }
 
-  mVoECallReport = webrtc::VoECallReport::GetInterface(mVoiceEngine);
-  if (!mVoECallReport) {
-    return;
-  }
-
   mChannel = mVoEBase->CreateChannel();
   if (mChannel < 0) {
     return;
   }
   mNullTransport = new NullTransport();
   if (mVoENetwork->RegisterExternalTransport(mChannel, *mNullTransport)) {
     return;
   }
@@ -564,34 +559,16 @@ MediaEngineWebRTCAudioSource::Process(in
                                                 length);
       moz_free(buffer);
       if (res == -1) {
         return;
       }
     }
   }
 
-#ifdef PR_LOGGING
-  mSamples += length;
-  if (mSamples > samplingFreq) {
-    mSamples %= samplingFreq; // just in case mSamples >> samplingFreq
-    if (PR_LOG_TEST(GetMediaManagerLog(), PR_LOG_DEBUG)) {
-      webrtc::EchoStatistics echo;
-
-      mVoECallReport->GetEchoMetricSummary(echo);
-#define DUMP_STATVAL(x) (x).min, (x).max, (x).average
-      LOG(("Echo: ERL: %d/%d/%d, ERLE: %d/%d/%d, RERL: %d/%d/%d, NLP: %d/%d/%d",
-           DUMP_STATVAL(echo.erl),
-           DUMP_STATVAL(echo.erle),
-           DUMP_STATVAL(echo.rerl),
-           DUMP_STATVAL(echo.a_nlp)));
-    }
-  }
-#endif
-
   MonitorAutoLock lock(mMonitor);
   if (mState != kStarted)
     return;
 
   uint32_t len = mSources.Length();
   for (uint32_t i = 0; i < len; i++) {
     nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(length * sizeof(sample));
 
--- a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -41,18 +41,18 @@ MediaEngineWebRTCVideoSource::FrameSizeC
   mHeight = h;
   LOG(("Video FrameSizeChange: %ux%u", w, h));
   return 0;
 }
 
 // ViEExternalRenderer Callback. Process every incoming frame here.
 int
 MediaEngineWebRTCVideoSource::DeliverFrame(
-   unsigned char* buffer, int size, uint32_t time_stamp, int64_t render_time,
-   void *handle)
+   unsigned char* buffer, int size, uint32_t time_stamp,
+   int64_t ntp_time_ms, int64_t render_time, void *handle)
 {
   // Check for proper state.
   if (mState != kStarted) {
     LOG(("DeliverFrame: video not started"));
     return 0;
   }
 
   if (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2)) != size) {
@@ -82,18 +82,18 @@ MediaEngineWebRTCVideoSource::DeliverFra
   data.mPicY = 0;
   data.mPicSize = IntSize(mWidth, mHeight);
   data.mStereoMode = StereoMode::MONO;
 
   videoImage->SetData(data);
 
 #ifdef DEBUG
   static uint32_t frame_num = 0;
-  LOGFRAME(("frame %d (%dx%d); timestamp %u, render_time %lu", frame_num++,
-            mWidth, mHeight, time_stamp, render_time));
+  LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %lu, render_time %lu", frame_num++,
+            mWidth, mHeight, time_stamp, ntp_time_ms, render_time));
 #endif
 
   // we don't touch anything in 'this' until here (except for snapshot,
   // which has it's own lock)
   MonitorAutoLock lock(mMonitor);
 
   // implicitly releases last image
   mImage = image.forget();
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -97,16 +97,18 @@ interface HTMLMediaElement : HTMLElement
   [Pref="media.webvtt.enabled"]
   TextTrack addTextTrack(TextTrackKind kind,
                          optional DOMString label = "",
                          optional DOMString language = "");
 };
 
 // Mozilla extensions:
 partial interface HTMLMediaElement {
+  [ChromeOnly]
+  readonly attribute MediaSource? mozMediaSourceObject;
   attribute MediaStream? mozSrcObject;
   attribute boolean mozPreservesPitch;
   readonly attribute boolean mozAutoplayEnabled;
 
   // NB: for internal use with the video controls:
   [Func="IsChromeOrXBL"] attribute boolean mozMediaStatisticsShowing;
   [Func="IsChromeOrXBL"] attribute boolean mozAllowCasting;
   [Func="IsChromeOrXBL"] attribute boolean mozIsCasting;
--- a/dom/webidl/MediaSource.webidl
+++ b/dom/webidl/MediaSource.webidl
@@ -30,9 +30,11 @@ interface MediaSource : EventTarget {
   attribute unrestricted double duration;
   [NewObject, Throws]
   SourceBuffer addSourceBuffer(DOMString type);
   [Throws]
   void removeSourceBuffer(SourceBuffer sourceBuffer);
   [Throws]
   void endOfStream(optional MediaSourceEndOfStreamError error);
   static boolean isTypeSupported(DOMString type);
+  [ChromeOnly]
+  readonly attribute DOMString mozDebugReaderData;
 };
--- a/dom/webidl/Response.webidl
+++ b/dom/webidl/Response.webidl
@@ -14,16 +14,17 @@ interface Response {
   [NewObject] static Response error();
   [Throws,
    NewObject] static Response redirect(USVString url, optional unsigned short status = 302);
 
   readonly attribute ResponseType type;
 
   readonly attribute USVString url;
   readonly attribute unsigned short status;
+  readonly attribute boolean ok;
   readonly attribute ByteString statusText;
   [SameObject] readonly attribute Headers headers;
 
   [NewObject] Response clone();
 };
 Response implements Body;
 
 dictionary ResponseInit {
--- a/dom/workers/test/fetch/worker_test_response.js
+++ b/dom/workers/test/fetch/worker_test_response.js
@@ -47,16 +47,30 @@ function testRedirect() {
       var res = Response.redirect(".", failStatus[i]);
       ok(false, "Invalid status code should fail " + failStatus[i]);
     } catch(e) {
       is(e.name, "RangeError", "Invalid status code should fail " + failStatus[i]);
     }
   }
 }
 
+function testOk() {
+  var r1 = new Response("", { status: 200});
+  ok(r1.ok, "Response with status 200 should have ok true");
+
+  var r2 = new Response("", { status: 204});
+  ok(r2.ok, "Response with status 204 should have ok true");
+
+  var r3 = new Response("", { status: 299});
+  ok(r3.ok, "Response with status 299 should have ok true");
+
+  var r4 = new Response("", { status: 302});
+  ok(!r4.ok, "Response with status 302 should have ok false");
+}
+
 function testBodyUsed() {
   var res = new Response("Sample body");
   ok(!res.bodyUsed, "bodyUsed is initially false.");
   return res.text().then((v) => {
     is(v, "Sample body", "Body should match");
     ok(res.bodyUsed, "After reading body, bodyUsed should be true.");
   }).then(() => {
     return res.blob().then((v) => {
@@ -133,16 +147,17 @@ function testBodyExtraction() {
 }
 
 onmessage = function() {
   var done = function() { postMessage({ type: 'finish' }) }
 
   testDefaultCtor();
   testClone();
   testRedirect();
+  testOk();
 
   Promise.resolve()
     .then(testBodyCreation)
     .then(testBodyUsed)
     .then(testBodyExtraction)
     // Put more promise based tests here.
     .then(done)
     .catch(function(e) {
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -362,17 +362,17 @@ TextureClientD3D11::BorrowDrawTarget()
       gfxWarning() << "Invalid draw target for borrowing";
   }
   return mDrawTarget;
 }
 
 static const GUID sD3D11TextureUsage =
 { 0xd89275b0, 0x6c7d, 0x4038, { 0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e } };
 
-/* This class get's it's lifetime tied to a D3D texture
+/* This class gets its lifetime tied to a D3D texture
  * and increments memory usage on construction and decrements
  * on destruction */
 class TextureMemoryMeasurer : public IUnknown
 {
 public:
   TextureMemoryMeasurer(size_t aMemoryUsed)
   {
     mMemoryUsed = aMemoryUsed;
--- a/intl/lwbrk/th_char.h
+++ b/intl/lwbrk/th_char.h
@@ -5,17 +5,16 @@ and its documentation for any purpose is
 provided that the above copyright notice appear in all copies and
 that both that copyright notice and this permission notice appear
 in supporting documentation.  Samphan Raruenrom makes no
 representations about the suitability of this software for any
 purpose.  It is provided "as is" without express or implied warranty.
 */
 #ifndef __TH_CHAR_H__
 #define __TH_CHAR_H__
-#include "nscore.h"
 
 
 typedef unsigned char	tis_char;
 
 #ifdef TH_UNICODE
 /*
  * The char16_t type is only usable in C++ code, so we need this ugly hack to
  * select a binary compatible C type for the expat C code to use.
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -185,25 +185,30 @@ BackgroundChildImpl::DeallocPFileDescrip
 
   delete static_cast<FileDescriptorSetChild*>(aActor);
   return true;
 }
 
 BackgroundChildImpl::PVsyncChild*
 BackgroundChildImpl::AllocPVsyncChild()
 {
-  return new mozilla::layout::VsyncChild();
+  nsRefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild();
+  // There still has one ref-count after return, and it will be released in
+  // DeallocPVsyncChild().
+  return actor.forget().take();
 }
 
 bool
 BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
 {
   MOZ_ASSERT(aActor);
 
-  delete static_cast<mozilla::layout::VsyncChild*>(aActor);
+  // This actor already has one ref-count. Please check AllocPVsyncChild().
+  nsRefPtr<mozilla::layout::VsyncChild> actor =
+      dont_AddRef(static_cast<mozilla::layout::VsyncChild*>(aActor));
   return true;
 }
 
 // -----------------------------------------------------------------------------
 // BroadcastChannel API
 // -----------------------------------------------------------------------------
 
 dom::PBroadcastChannelChild*
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -142,16 +142,19 @@ class AsmJSNumLit
         Value scalar_;
         jit::SimdConstant simd_;
     } value;
 
   public:
     static AsmJSNumLit Create(Which w, Value v) {
         AsmJSNumLit lit;
         lit.which_ = w;
+        // Force float32 coercion, as the caller may have not done it.
+        if (w == Float)
+            v = Float32Value(v.toNumber());
         lit.value.scalar_ = v;
         MOZ_ASSERT(!lit.isSimd());
         return lit;
     }
 
     static AsmJSNumLit Create(Which w, jit::SimdConstant c) {
         AsmJSNumLit lit;
         lit.which_ = w;
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -414,19 +414,36 @@ case "$target" in
             AC_MSG_ERROR([The major versions of \$CC and \$CXX do not match.])
         fi
 
         AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
         AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
 
         if test "$_CC_MAJOR_VERSION" = "18"; then
             _CC_SUITE=12
+            MSVC_C_RUNTIME_DLL=msvcr120.dll
+            MSVC_CXX_RUNTIME_DLL=msvcp120.dll
+        elif test "$_CC_MAJOR_VERSION" = "19"; then
+            _CC_SUITE=14
+            MSVC_C_RUNTIME_DLL=vcruntime140.dll
+            MSVC_CXX_RUNTIME_DLL=msvcp140.dll
+            MSVC_APPCRT_DLL=appcrt140.dll
+            MSVC_DESKTOPCRT_DLL=desktopcrt140.dll
+
+            # -Wv:18 disables all warnings introduced after VS2013
+            # See http://blogs.msdn.com/b/vcblog/archive/2014/11/12/improvements-to-warnings-in-the-c-compiler.aspx
+            CFLAGS="$CFLAGS -Wv:18"
+            CXXFLAGS="$CXXFLAGS -Wv:18"
         else
             AC_MSG_ERROR([This version ($CC_VERSION) of the MSVC compiler is unsupported. See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         fi
+        AC_SUBST(MSVC_C_RUNTIME_DLL)
+        AC_SUBST(MSVC_CXX_RUNTIME_DLL)
+        AC_SUBST(MSVC_APPCRT_DLL)
+        AC_SUBST(MSVC_DESKTOPCRT_DLL)
 
         dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
         dnl not something else like "magnetic tape manipulation utility".
         MSMT_TOOL=`${MT-mt} 2>&1|grep 'Microsoft (R) Manifest Tool'`
         if test -z "$MSMT_TOOL"; then
           AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
         fi
 
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -377,20 +377,17 @@ class FullParseHandler
         genName->markAsAssigned();
         ParseNode *genInit = newBinary(PNK_ASSIGN, genName, makeGen);
 
         ParseNode *initialYield = newYieldExpression(yieldPos.begin, nullptr, genInit,
                                                      JSOP_INITIALYIELD);
         if (!initialYield)
             return false;
 
-        initialYield->pn_next = stmtList->pn_head;
-        stmtList->pn_head = initialYield;
-        stmtList->pn_count++;
-
+        stmtList->prepend(initialYield);
         return true;
     }
 
     ParseNode *newEmptyStatement(const TokenPos &pos) {
         return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
     }
 
     ParseNode *newImportDeclaration(ParseNode *importSpecSet,
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -843,16 +843,25 @@ class ParseNode
         MOZ_ASSERT(pn_arity == PN_LIST);
         MOZ_ASSERT(pn->pn_pos.begin >= pn_pos.begin);
         pn_pos.end = pn->pn_pos.end;
         *pn_tail = pn;
         pn_tail = &pn->pn_next;
         pn_count++;
     }
 
+    void prepend(ParseNode *pn) {
+        MOZ_ASSERT(pn_arity == PN_LIST);
+        pn->pn_next = pn_head;
+        pn_head = pn;
+        if (pn_tail == &pn_head)
+            pn_tail = &pn->pn_next;
+        pn_count++;
+    }
+
     void checkListConsistency()
 #ifndef DEBUG
     {}
 #endif
     ;
 
     enum AllowConstantObjects {
         DontAllowObjects = 0,
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2248,21 +2248,17 @@ Parser<FullParseHandler>::finishFunction
         }
 
         ParseNode *item = handler.new_<UnaryNode>(PNK_SEMI, JSOP_NOP,
                                                   TokenPos(body->pn_pos.begin, body->pn_pos.begin),
                                                   prelude);
         if (!item)
             return false;
 
-        item->pn_next = body->pn_head;
-        body->pn_head = item;
-        if (body->pn_tail == &body->pn_head)
-            body->pn_tail = &item->pn_next;
-        ++body->pn_count;
+        body->prepend(item);
         body->pn_xflags |= PNX_DESTRUCT;
     }
 
     MOZ_ASSERT(pn->pn_funbox == funbox);
     MOZ_ASSERT(pn->pn_body->isKind(PNK_ARGSBODY));
     pn->pn_body->append(body);
 
     return true;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1126251.js
@@ -0,0 +1,36 @@
+load(libdir + "asm.js");
+
+var v = asmLink(asmCompile('global', `
+    "use asm";
+    var frd = global.Math.fround;
+    function e() {
+        var x = frd(.1e+71);
+        x = frd(x / x);
+        return +x;
+    }
+    return e;
+`), this)();
+
+assertEq(v, NaN);
+
+if (!isSimdAvailable() || typeof SIMD === 'undefined') {
+    quit(0);
+}
+
+var v = asmLink(asmCompile('global', `
+    "use asm";
+    var frd = global.Math.fround;
+    var float32x4 = global.SIMD.float32x4;
+    var splat = float32x4.splat;
+    function e() {
+        var v = float32x4(0,0,0,0);
+        var x = frd(0.);
+        v = splat(.1e+71);
+        x = v.x;
+        x = frd(x / x);
+        return +x;
+    }
+    return e;
+`), this)();
+
+assertEq(v, NaN);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/mutable-proto-teleporting.js
@@ -0,0 +1,18 @@
+// The teleporting optimization should work correctly
+// when we modify an object's proto.
+
+var A = {x: 1};
+var B = Object.create(A);
+
+var C = {};
+C.__proto__ = B;
+
+function f() {
+    for (var i=0; i<25; i++) {
+        assertEq(C.x, (i <= 20) ? 1 : 3);
+        if (i === 20) {
+            B.x = 3;
+        }
+    }
+}
+f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/teleporting-mutable-proto.js
@@ -0,0 +1,14 @@
+var A = {x: 3};
+var B = Object.create(A);
+var C = Object.create(B);
+var D = Object.create(C);
+
+function f() {
+    for (var i=0; i<30; i++) {
+	assertEq(D.x, (i <= 20) ? 3 : 10);
+	if (i === 20) {
+	    C.__proto__ = {x: 10};
+	}
+    }
+}
+f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug1126754.js
@@ -0,0 +1,9 @@
+// |jit-test| error:SyntaxError
+
+(function() {
+    with ({}) {}
+    function f() {
+        ({ *h(){} })
+    }
+    function f
+})()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1124653.js
@@ -0,0 +1,5 @@
+var o = {};
+gczeal(14);
+for (var i = 0; i < 200; i++) {
+    with (o) { }
+}
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -347,127 +347,49 @@ class CachePage
     }
 
   private:
     char data_[kPageSize];   // The cached data.
     static const int kValidityMapSize = kPageSize >> kLineShift;
     char validity_map_[kValidityMapSize];  // One byte per line.
 };
 
-class Redirection;
-
-class SimulatorRuntime
-{
-    friend class AutoLockSimulatorRuntime;
-
-    Redirection *redirection_;
-
-    // ICache checking.
-    struct ICacheHasher {
-        typedef void *Key;
-        typedef void *Lookup;
-        static HashNumber hash(const Lookup &l);
-        static bool match(const Key &k, const Lookup &l);
-    };
-
-  public:
-    typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
-
-  protected:
-    ICacheMap icache_;
-
-    // Synchronize access between main thread and compilation threads.
-    PRLock *lock_;
-    mozilla::DebugOnly<PRThread *> lockOwner_;
-
-  public:
-    SimulatorRuntime()
-      : redirection_(nullptr),
-        lock_(nullptr),
-        lockOwner_(nullptr)
-    {}
-    ~SimulatorRuntime();
-    bool init() {
-        lock_ = PR_NewLock();
-        if (!lock_)
-            return false;
-        if (!icache_.init())
-            return false;
-        return true;
-    }
-    ICacheMap &icache() {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        return icache_;
-    }
-    Redirection *redirection() const {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        return redirection_;
-    }
-    void setRedirection(js::jit::Redirection *redirection) {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        redirection_ = redirection;
-    }
-};
-
-class AutoLockSimulatorRuntime
-{
-  protected:
-    SimulatorRuntime *srt_;
-
-  public:
-    AutoLockSimulatorRuntime(SimulatorRuntime *srt)
-      : srt_(srt)
-    {
-        PR_Lock(srt_->lock_);
-        MOZ_ASSERT(!srt_->lockOwner_);
-#ifdef DEBUG
-        srt_->lockOwner_ = PR_GetCurrentThread();
-#endif
-    }
-
-    ~AutoLockSimulatorRuntime() {
-        MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
-        srt_->lockOwner_ = nullptr;
-        PR_Unlock(srt_->lock_);
-    }
-};
-
 bool Simulator::ICacheCheckingEnabled = false;
 
 int64_t Simulator::StopSimAt = -1L;
 
-SimulatorRuntime *
-CreateSimulatorRuntime()
+Simulator *
+Simulator::Create()
 {
-    SimulatorRuntime *srt = js_new<SimulatorRuntime>();
-    if (!srt)
+    Simulator *sim = js_new<Simulator>();
+    if (!sim)
         return nullptr;
 
-    if (!srt->init()) {
-        js_delete(srt);
-        return nullptr;
+    if (!sim->init()) {
+        js_delete(sim);
+        return false;
     }
 
     if (getenv("ARM_SIM_ICACHE_CHECKS"))
         Simulator::ICacheCheckingEnabled = true;
 
     char *stopAtStr = getenv("ARM_SIM_STOP_AT");
     int64_t stopAt;
     if (stopAtStr && sscanf(stopAtStr, "%lld", &stopAt) == 1) {
         fprintf(stderr, "\nStopping simulation at icount %lld\n", stopAt);
         Simulator::StopSimAt = stopAt;
     }
 
-    return srt;
+    return sim;
 }
 
 void
-DestroySimulatorRuntime(SimulatorRuntime *srt)
+Simulator::Destroy(Simulator *sim)
 {
-    js_delete(srt);
+    js_delete(sim);
 }
 
 // The ArmDebugger class is used by the simulator while debugging simulated ARM
 // code.
 class ArmDebugger {
   public:
     explicit ArmDebugger(Simulator *sim) : sim_(sim) { }
 
@@ -995,48 +917,48 @@ static bool
 AllOnOnePage(uintptr_t start, int size)
 {
     intptr_t start_page = (start & ~CachePage::kPageMask);
     intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
     return start_page == end_page;
 }
 
 static CachePage *
-GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
+GetCachePage(Simulator::ICacheMap &i_cache, void *page)
 {
     MOZ_ASSERT(Simulator::ICacheCheckingEnabled);
 
-    SimulatorRuntime::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
+    Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
     if (p)
         return p->value();
 
     CachePage *new_page = js_new<CachePage>();
     if (!i_cache.add(p, page, new_page))
         return nullptr;
     return new_page;
 }
 
 // Flush from start up to and not including start + size.
 static void
-FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
+FlushOnePage(Simulator::ICacheMap &i_cache, intptr_t start, int size)
 {
     MOZ_ASSERT(size <= CachePage::kPageSize);
     MOZ_ASSERT(AllOnOnePage(start, size - 1));
     MOZ_ASSERT((start & CachePage::kLineMask) == 0);
     MOZ_ASSERT((size & CachePage::kLineMask) == 0);
 
     void *page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
     int offset = (start & CachePage::kPageMask);
     CachePage *cache_page = GetCachePage(i_cache, page);
     char *valid_bytemap = cache_page->validityByte(offset);
     memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
 static void
-FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
+FlushICache(Simulator::ICacheMap &i_cache, void *start_addr, size_t size)
 {
     intptr_t start = reinterpret_cast<intptr_t>(start_addr);
     int intra_line = (start & CachePage::kLineMask);
     start -= intra_line;
     size += intra_line;
     size = ((size - 1) | CachePage::kLineMask) + 1;
     int offset = (start & CachePage::kPageMask);
     while (!AllOnOnePage(start, size - 1)) {
@@ -1047,17 +969,17 @@ FlushICache(SimulatorRuntime::ICacheMap 
         MOZ_ASSERT((start & CachePage::kPageMask) == 0);
         offset = 0;
     }
     if (size != 0)
         FlushOnePage(i_cache, start, size);
 }
 
 static void
-CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
+CheckICache(Simulator::ICacheMap &i_cache, SimInstruction *instr)
 {
     intptr_t address = reinterpret_cast<intptr_t>(instr);
     void *page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
     void *line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
     int offset = (address & CachePage::kPageMask);
     CachePage* cache_page = GetCachePage(i_cache, page);
     char *cache_valid_byte = cache_page->validityByte(offset);
     bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
@@ -1070,23 +992,23 @@ CheckICache(SimulatorRuntime::ICacheMap 
     } else {
         // Cache miss. Load memory into the cache.
         memcpy(cached_line, line, CachePage::kLineLength);
         *cache_valid_byte = CachePage::LINE_VALID;
     }
 }
 
 HashNumber
-SimulatorRuntime::ICacheHasher::hash(const Lookup &l)
+Simulator::ICacheHasher::hash(const Lookup &l)
 {
     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
 }
 
 bool
-SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
+Simulator::ICacheHasher::match(const Key &k, const Lookup &l)
 {
     MOZ_ASSERT((reinterpret_cast<intptr_t>(k) & CachePage::kPageMask) == 0);
     MOZ_ASSERT((reinterpret_cast<intptr_t>(l) & CachePage::kPageMask) == 0);
     return k == l;
 }
 
 void
 Simulator::setLastDebuggerInput(char *input)
@@ -1096,40 +1018,29 @@ Simulator::setLastDebuggerInput(char *in
 }
 
 void
 Simulator::FlushICache(void *start_addr, size_t size)
 {
     JitSpewCont(JitSpew_CacheFlush, "[%p %zx]", start_addr, size);
     if (!Simulator::ICacheCheckingEnabled)
         return;
-    SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
-    AutoLockSimulatorRuntime alsr(srt);
-    js::jit::FlushICache(srt->icache(), start_addr, size);
+    js::jit::FlushICache(Simulator::Current()->icache(), start_addr, size);
 }
 
-Simulator::~Simulator()
-{
-    js_free(stack_);
-}
-
-Simulator::Simulator(SimulatorRuntime *srt)
-  : srt_(srt)
+Simulator::Simulator()
 {
     // Set up simulator support first. Some of this information is needed to
     // setup the architecture state.
 
-    // Allocate 2MB for the stack. Note that we will only use 1MB, see also
-    // Simulator::stackLimit().
-    static const size_t stackSize = 2 * 1024*1024;
-    stack_ = reinterpret_cast<char*>(js_malloc(stackSize));
-    if (!stack_) {
-        MOZ_ReportAssertionFailure("[unhandlable oom] Simulator stack", __FILE__, __LINE__);
-        MOZ_CRASH();
-    }
+    // Note, allocation and anything that depends on allocated memory is
+    // deferred until init(), in order to handle OOM properly.
+
+    stack_ = nullptr;
+    stackLimit_ = 0;
     pc_modified_ = false;
     icount_ = 0L;
     resume_pc_ = 0;
     break_pc_ = nullptr;
     break_instr_ = 0;
     single_stepping_ = false;
     single_step_callback_ = nullptr;
     single_step_callback_arg_ = nullptr;
@@ -1156,111 +1067,126 @@ Simulator::Simulator(SimulatorRuntime *s
     FPSCR_default_NaN_mode_ = true;
 
     inv_op_vfp_flag_ = false;
     div_zero_vfp_flag_ = false;
     overflow_vfp_flag_ = false;
     underflow_vfp_flag_ = false;
     inexact_vfp_flag_ = false;
 
-    // The sp is initialized to point to the bottom (high address) of the
-    // allocated stack area. To be safe in potential stack underflows we leave
-    // some buffer below.
-    registers_[sp] = reinterpret_cast<int32_t>(stack_) + stackSize - 64;
-
     // The lr and pc are initialized to a known bad value that will cause an
     // access violation if the simulator ever tries to execute it.
     registers_[pc] = bad_lr;
     registers_[lr] = bad_lr;
 
     lastDebuggerInput_ = nullptr;
+
+    redirection_ = nullptr;
+}
+
+bool
+Simulator::init()
+{
+    if (!icache_.init())
+        return false;
+
+    // Allocate 2MB for the stack. Note that we will only use 1MB, see below.
+    static const size_t stackSize = 2 * 1024*1024;
+    stack_ = reinterpret_cast<char*>(js_malloc(stackSize));
+    if (!stack_)
+        return false;
+
+    // Leave a safety margin of 1MB to prevent overrunning the stack when
+    // pushing values (total stack size is 2MB).
+    stackLimit_ = reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
+
+    // The sp is initialized to point to the bottom (high address) of the
+    // allocated stack area. To be safe in potential stack underflows we leave
+    // some buffer below.
+    registers_[sp] = reinterpret_cast<int32_t>(stack_) + stackSize - 64;
+
+    return true;
 }
 
 // When the generated code calls a VM function (masm.callWithABI) we need to
 // call that function instead of trying to execute it with the simulator
 // (because it's x86 code instead of arm code). We do that by redirecting the VM
 // call to a svc (Supervisor Call) instruction that is handled by the
 // simulator. We write the original destination of the jump just at a known
 // offset from the svc instruction so the simulator knows what to call.
 class Redirection
 {
-    friend class SimulatorRuntime;
-
-    Redirection(void *nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
+    friend class Simulator;
+
+    Redirection(void *nativeFunction, ABIFunctionType type, Simulator *sim)
       : nativeFunction_(nativeFunction),
         swiInstruction_(Assembler::AL | (0xf * (1 << 24)) | kCallRtRedirected),
         type_(type),
         next_(nullptr)
     {
-        next_ = srt->redirection();
+        next_ = sim->redirection();
         if (Simulator::ICacheCheckingEnabled)
-            FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
-        srt->setRedirection(this);
+            FlushICache(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
+        sim->setRedirection(this);
     }
 
   public:
     void *addressOfSwiInstruction() { return &swiInstruction_; }
     void *nativeFunction() const { return nativeFunction_; }
     ABIFunctionType type() const { return type_; }
 
     static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
-        PerThreadData *pt = TlsPerThreadData.get();
-        SimulatorRuntime *srt = pt->simulatorRuntime();
-        AutoLockSimulatorRuntime alsr(srt);
-
-        MOZ_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
-
-        Redirection *current = srt->redirection();
+        Simulator *sim = Simulator::Current();
+        Redirection *current = sim->redirection();
         for (; current != nullptr; current = current->next_) {
             if (current->nativeFunction_ == nativeFunction) {
                 MOZ_ASSERT(current->type() == type);
                 return current;
             }
         }
 
         Redirection *redir = (Redirection *)js_malloc(sizeof(Redirection));
         if (!redir) {
             MOZ_ReportAssertionFailure("[unhandlable oom] Simulator redirection",
                                        __FILE__, __LINE__);
             MOZ_CRASH();
         }
-        new(redir) Redirection(nativeFunction, type, srt);
+        new(redir) Redirection(nativeFunction, type, sim);
         return redir;
     }
 
     static Redirection *FromSwiInstruction(SimInstruction *swiInstruction) {
         uint8_t *addrOfSwi = reinterpret_cast<uint8_t*>(swiInstruction);
         uint8_t *addrOfRedirection = addrOfSwi - offsetof(Redirection, swiInstruction_);
         return reinterpret_cast<Redirection*>(addrOfRedirection);
     }
 
   private:
     void *nativeFunction_;
     uint32_t swiInstruction_;
     ABIFunctionType type_;
     Redirection *next_;
 };
 
-/* static */ void *
-Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
+Simulator::~Simulator()
 {
-    Redirection *redirection = Redirection::Get(nativeFunction, type);
-    return redirection->addressOfSwiInstruction();
-}
-
-SimulatorRuntime::~SimulatorRuntime()
-{
+    js_free(stack_);
     Redirection *r = redirection_;
     while (r) {
         Redirection *next = r->next_;
         js_delete(r);
         r = next;
     }
-    if (lock_)
-        PR_DestroyLock(lock_);
+}
+
+/* static */ void *
+Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
+{
+    Redirection *redirection = Redirection::Get(nativeFunction, type);
+    return redirection->addressOfSwiInstruction();
 }
 
 // Sets the register in the architecture state. It will also deal with updating
 // Simulator internal state for special registers such as PC.
 void
 Simulator::set_register(int reg, int32_t value)
 {
     MOZ_ASSERT(reg >= 0 && reg < num_registers);
@@ -1625,19 +1551,23 @@ Simulator::writeDW(int32_t addr, int32_t
         printf("Unaligned write at 0x%08x\n", addr);
         MOZ_CRASH();
     }
 }
 
 uintptr_t
 Simulator::stackLimit() const
 {
-    // Leave a safety margin of 1MB to prevent overrunning the stack when
-    // pushing values (total stack size is 2MB).
-    return reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
+    return stackLimit_;
+}
+
+uintptr_t *
+Simulator::addressOfStackLimit()
+{
+    return &stackLimit_;
 }
 
 bool
 Simulator::overRecursed(uintptr_t newsp) const
 {
     if (newsp == 0)
         newsp = get_register(sp);
     return newsp <= stackLimit();
@@ -4165,20 +4095,18 @@ Simulator::decodeSpecialCondition(SimIns
         MOZ_CRASH();
     }
 }
 
 // Executes the current instruction.
 void
 Simulator::instructionDecode(SimInstruction *instr)
 {
-    if (Simulator::ICacheCheckingEnabled) {
-        AutoLockSimulatorRuntime alsr(srt_);
-        CheckICache(srt_->icache(), instr);
-    }
+    if (Simulator::ICacheCheckingEnabled)
+        CheckICache(icache(), instr);
 
     pc_modified_ = false;
 
     static const uint32_t kSpecialCondition = 15 << 28;
     if (instr->conditionField() == kSpecialCondition) {
         decodeSpecialCondition(instr);
     } else if (conditionallyExecute(instr)) {
         switch (instr->typeValue()) {
@@ -4436,70 +4364,31 @@ Simulator::call(uint8_t* entry, int argu
 
     int64_t result = (int64_t(get_register(r1)) << 32) | get_register(r0);
     return result;
 }
 
 Simulator *
 Simulator::Current()
 {
-    PerThreadData *pt = TlsPerThreadData.get();
-    Simulator *sim = pt->simulator();
-    if (!sim) {
-        sim = js_new<Simulator>(pt->simulatorRuntime());
-        pt->setSimulator(sim);
-    }
-
-    return sim;
+    return TlsPerThreadData.get()->simulator();
 }
 
 } // namespace jit
 } // namespace js
 
 js::jit::Simulator *
 JSRuntime::simulator() const
 {
     return simulator_;
 }
 
+uintptr_t *
+JSRuntime::addressOfSimulatorStackLimit()
+{
+    return simulator_->addressOfStackLimit();
+}
+
 js::jit::Simulator *
 js::PerThreadData::simulator() const
 {
     return runtime_->simulator();
 }
-
-void
-JSRuntime::setSimulator(js::jit::Simulator *sim)
-{
-    simulator_ = sim;
-    simulatorStackLimit_ = sim->stackLimit();
-}
-
-void
-js::PerThreadData::setSimulator(js::jit::Simulator *sim)
-{
-    runtime_->setSimulator(sim);
-}
-
-uintptr_t *
-JSRuntime::addressOfSimulatorStackLimit()
-{
-    return &simulatorStackLimit_;
-}
-
-js::jit::SimulatorRuntime *
-js::PerThreadData::simulatorRuntime() const
-{
-    return runtime_->simulatorRuntime();
-}
-
-js::jit::SimulatorRuntime *
-JSRuntime::simulatorRuntime() const
-{
-    return simulatorRuntime_;
-}
-
-void
-JSRuntime::setSimulatorRuntime(js::jit::SimulatorRuntime *srt)
-{
-    MOZ_ASSERT(!simulatorRuntime_);
-    simulatorRuntime_ = srt;
-}
--- a/js/src/jit/arm/Simulator-arm.h
+++ b/js/src/jit/arm/Simulator-arm.h
@@ -33,19 +33,18 @@
 
 #include "jit/arm/Architecture-arm.h"
 #include "jit/IonTypes.h"
 
 namespace js {
 namespace jit {
 
 class Simulator;
-class SimulatorRuntime;
-SimulatorRuntime *CreateSimulatorRuntime();
-void DestroySimulatorRuntime(SimulatorRuntime *srt);
+class Redirection;
+class CachePage;
 
 // When the SingleStepCallback is called, the simulator is about to execute
 // sim->get_pc() and the current machine state represents the completed
 // execution of the previous pc.
 typedef void (*SingleStepCallback)(void *arg, Simulator *sim, void *pc);
 
 // VFP rounding modes. See ARM DDI 0406B Page A2-29.
 enum VFPRoundingMode {
@@ -90,27 +89,35 @@ class Simulator
         d16, d17, d18, d19, d20, d21, d22, d23,
         d24, d25, d26, d27, d28, d29, d30, d31,
         num_d_registers = 32,
         q0 = 0, q1, q2, q3, q4, q5, q6, q7,
         q8, q9, q10, q11, q12, q13, q14, q15,
         num_q_registers = 16
     };
 
-    explicit Simulator(SimulatorRuntime *srt);
+    // Returns nullptr on OOM.
+    static Simulator *Create();
+
+    static void Destroy(Simulator *simulator);
+
+    // Constructor/destructor are for internal use only; use the static methods above.
+    Simulator();
     ~Simulator();
 
     // The currently executing Simulator instance. Potentially there can be one
     // for each native thread.
     static Simulator *Current();
 
     static inline uintptr_t StackLimit() {
         return Simulator::Current()->stackLimit();
     }
 
+    uintptr_t *addressOfStackLimit();
+
     // Accessors for register state. Reading the pc value adheres to the ARM
     // architecture specification and is off by a 8 from the currently executing
     // instruction.
     void set_register(int reg, int32_t value);
     int32_t get_register(int reg) const;
     double get_double_from_register_pair(int reg);
     void set_register_pair_from_double(int reg, double* value);
     void set_dw_register(int dreg, const int* dbl);
@@ -183,16 +190,18 @@ class Simulator
         bad_lr = -1,
         // A pc value used to signal the simulator to stop execution. Generally
         // the lr is set to this value on transition from native C code to
         // simulated execution, so that the simulator can "return" to the native
         // C code.
         end_sim_pc = -2
     };
 
+    bool init();
+
     // Checks if the current instruction should be executed based on its
     // condition bits.
     inline bool conditionallyExecute(SimInstruction* instr);
 
     // Helper functions to set the conditional flags in the architecture state.
     void setNZFlags(int32_t val);
     void setCFlag(bool val);
     void setVFlag(bool val);
@@ -328,16 +337,17 @@ class Simulator
     bool inv_op_vfp_flag_;
     bool div_zero_vfp_flag_;
     bool overflow_vfp_flag_;
     bool underflow_vfp_flag_;
     bool inexact_vfp_flag_;
 
     // Simulator support.
     char *stack_;
+    uintptr_t stackLimit_;
     bool pc_modified_;
     int64_t icount_;
 
     int32_t resume_pc_;
 
     // Debugger input.
     char *lastDebuggerInput_;
 
@@ -345,18 +355,16 @@ class Simulator
     SimInstruction *break_pc_;
     Instr break_instr_;
 
     // Single-stepping support
     bool single_stepping_;
     SingleStepCallback single_step_callback_;
     void *single_step_callback_arg_;
 
-    SimulatorRuntime *srt_;
-
     // A stop is watched if its code is less than kNumOfWatchedStops.
     // Only watched stops support enabling/disabling and the counter feature.
     static const uint32_t kNumOfWatchedStops = 256;
 
     // Breakpoint is disabled if bit 31 is set.
     static const uint32_t kStopDisabledBit = 1 << 31;
 
     // A stop is enabled, meaning the simulator will stop when meeting the
@@ -369,16 +377,45 @@ class Simulator
     };
     StopCountAndDesc watched_stops_[kNumOfWatchedStops];
 
   public:
     int64_t icount() {
         return icount_;
     }
 
+  private:
+    Redirection *redirection_;
+
+    // ICache checking.
+    struct ICacheHasher {
+        typedef void *Key;
+        typedef void *Lookup;
+        static HashNumber hash(const Lookup &l);
+        static bool match(const Key &k, const Lookup &l);
+    };
+
+  public:
+    typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
+
+  protected:
+    ICacheMap icache_;
+
+  public:
+    ICacheMap &icache() {
+        return icache_;
+    }
+
+    Redirection *redirection() const {
+        return redirection_;
+    }
+
+    void setRedirection(js::jit::Redirection *redirection) {
+        redirection_ = redirection;
+    }
 };
 
 #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror)             \
     JS_BEGIN_MACRO                                                              \
         if (cx->runtime()->simulator()->overRecursedWithExtra(extra)) {         \
             js_ReportOverRecursed(cx);                                          \
             onerror;                                                            \
         }                                                                       \
--- a/js/src/jit/mips/Simulator-mips.cpp
+++ b/js/src/jit/mips/Simulator-mips.cpp
@@ -481,125 +481,49 @@ class CachePage {
     }
 
   private:
     char data_[kPageSize];   // The cached data.
     static const int kValidityMapSize = kPageSize >> kLineShift;
     char validity_map_[kValidityMapSize];  // One byte per line.
 };
 
-class Redirection;
-
-class SimulatorRuntime
-{
-    friend class AutoLockSimulatorRuntime;
-
-    Redirection *redirection_;
-
-    // ICache checking.
-    struct ICacheHasher {
-        typedef void *Key;
-        typedef void *Lookup;
-        static HashNumber hash(const Lookup &l);
-        static bool match(const Key &k, const Lookup &l);
-    };
-
-  public:
-    typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
-
-  protected:
-    ICacheMap icache_;
-
-    // Synchronize access between main thread and compilation threads.
-    PRLock *lock_;
-    mozilla::DebugOnly<PRThread *> lockOwner_;
-
-  public:
-    SimulatorRuntime()
-      : redirection_(nullptr),
-        lock_(nullptr),
-        lockOwner_(nullptr) {}
-    ~SimulatorRuntime();
-    bool init() {
-        lock_ = PR_NewLock();
-        if (!lock_)
-            return false;
-        if (!icache_.init())
-            return false;
-        return true;
-    }
-    ICacheMap &icache() {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        return icache_;
-    }
-    Redirection *redirection() const {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        return redirection_;
-    }
-    void setRedirection(js::jit::Redirection *redirection) {
-        MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-        redirection_ = redirection;
-    }
-};
-
-class AutoLockSimulatorRuntime
-{
-  protected:
-    SimulatorRuntime *srt_;
-
-  public:
-    AutoLockSimulatorRuntime(SimulatorRuntime *srt)
-        : srt_(srt) {
-        PR_Lock(srt_->lock_);
-        MOZ_ASSERT(!srt_->lockOwner_);
-#ifdef DEBUG
-        srt_->lockOwner_ = PR_GetCurrentThread();
-#endif
-    }
-
-    ~AutoLockSimulatorRuntime() {
-        MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
-        srt_->lockOwner_ = nullptr;
-        PR_Unlock(srt_->lock_);
-    }
-};
-
 bool Simulator::ICacheCheckingEnabled = false;
 
 int Simulator::StopSimAt = -1;
 
-SimulatorRuntime *
-CreateSimulatorRuntime()
+Simulator *
+Simulator::Create()
 {
-    SimulatorRuntime *srt = js_new<SimulatorRuntime>();
-    if (!srt)
+    Simulator *sim = js_new<Simulator>();
+    if (!sim)
         return nullptr;
 
-    if (!srt->init()) {
-        js_delete(srt);
-        return nullptr;
+    if (!sim->icache_.init()) {
+        js_delete(sim);
+        return false;
     }
 
     if (getenv("MIPS_SIM_ICACHE_CHECKS"))
         Simulator::ICacheCheckingEnabled = true;
 
     char *stopAtStr = getenv("MIPS_SIM_STOP_AT");
     int64_t stopAt;
     if (stopAtStr && sscanf(stopAtStr, "%lld", &stopAt) == 1) {
         fprintf(stderr, "\nStopping simulation at icount %lld\n", stopAt);
         Simulator::StopSimAt = stopAt;
     }
 
-    return srt;
+    return sim;
 }
 
 void
-DestroySimulatorRuntime(SimulatorRuntime *srt)
+Simulator::Destroy(Simulator *sim)
 {
-    js_delete(srt);
+    js_delete(sim);
 }
 
 // The MipsDebugger class is used by the simulator while debugging simulated
 // code.
 class MipsDebugger
 {
   public:
     explicit MipsDebugger(Simulator *sim) : sim_(sim) { }
@@ -1188,45 +1112,45 @@ AllOnOnePage(uintptr_t start, int size)
 void
 Simulator::setLastDebuggerInput(char *input)
 {
     js_free(lastDebuggerInput_);
     lastDebuggerInput_ = input;
 }
 
 static CachePage *
-GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
+GetCachePage(Simulator::ICacheMap &i_cache, void *page)
 {
-    SimulatorRuntime::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
+    Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
     if (p)
         return p->value();
 
     CachePage *new_page = js_new<CachePage>();
     if (!i_cache.add(p, page, new_page))
         return nullptr;
     return new_page;
 }
 
 // Flush from start up to and not including start + size.
 static void
-FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
+FlushOnePage(Simulator::ICacheMap &i_cache, intptr_t start, int size)
 {
     MOZ_ASSERT(size <= CachePage::kPageSize);
     MOZ_ASSERT(AllOnOnePage(start, size - 1));
     MOZ_ASSERT((start & CachePage::kLineMask) == 0);
     MOZ_ASSERT((size & CachePage::kLineMask) == 0);
     void *page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
     int offset = (start & CachePage::kPageMask);
     CachePage *cache_page = GetCachePage(i_cache, page);
     char *valid_bytemap = cache_page->validityByte(offset);
     memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
 static void
-FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
+FlushICache(Simulator::ICacheMap &i_cache, void *start_addr, size_t size)
 {
     intptr_t start = reinterpret_cast<intptr_t>(start_addr);
     int intra_line = (start & CachePage::kLineMask);
     start -= intra_line;
     size += intra_line;
     size = ((size - 1) | CachePage::kLineMask) + 1;
     int offset = (start & CachePage::kPageMask);
     while (!AllOnOnePage(start, size - 1)) {
@@ -1238,17 +1162,17 @@ FlushICache(SimulatorRuntime::ICacheMap 
         offset = 0;
     }
     if (size != 0) {
         FlushOnePage(i_cache, start, size);
     }
 }
 
 static void
-CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
+CheckICache(Simulator::ICacheMap &i_cache, SimInstruction *instr)
 {
     intptr_t address = reinterpret_cast<intptr_t>(instr);
     void *page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
     void *line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
     int offset = (address & CachePage::kPageMask);
     CachePage *cache_page = GetCachePage(i_cache, page);
     char *cache_valid_byte = cache_page->validityByte(offset);
     bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
@@ -1261,56 +1185,50 @@ CheckICache(SimulatorRuntime::ICacheMap 
     } else {
         // Cache miss.  Load memory into the cache.
         memcpy(cached_line, line, CachePage::kLineLength);
         *cache_valid_byte = CachePage::LINE_VALID;
     }
 }
 
 HashNumber
-SimulatorRuntime::ICacheHasher::hash(const Lookup &l)
+Simulator::ICacheHasher::hash(const Lookup &l)
 {
     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
 }
 
 bool
-SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
+Simulator::ICacheHasher::match(const Key &k, const Lookup &l)
 {
     MOZ_ASSERT((reinterpret_cast<intptr_t>(k) & CachePage::kPageMask) == 0);
     MOZ_ASSERT((reinterpret_cast<intptr_t>(l) & CachePage::kPageMask) == 0);
     return k == l;
 }
 
 void
 Simulator::FlushICache(void *start_addr, size_t size)
 {
-    SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
-    AutoLockSimulatorRuntime alsr(srt);
-    js::jit::FlushICache(srt->icache(), start_addr, size);
+    js::jit::FlushICache(Simulator::Current()->icache(), start_addr, size);
 }
 
-Simulator::~Simulator()
-{
-    js_free(stack_);
-}
-
-Simulator::Simulator(SimulatorRuntime *srt)
-    : srt_(srt)
+Simulator::Simulator()
 {
     // Set up simulator support first. Some of this information is needed to
     // setup the architecture state.
 
-    // Allocate 2MB for the stack. Note that we will only use 1MB, see also
-    // Simulator::stackLimit().
+    // Allocate 2MB for the stack. Note that we will only use 1MB, see below.
     static const size_t stackSize = 2 * 1024 * 1024;
     stack_ = static_cast<char*>(js_malloc(stackSize));
     if (!stack_) {
         MOZ_ReportAssertionFailure("[unhandlable oom] Simulator stack", __FILE__, __LINE__);
         MOZ_CRASH();
     }
+    // Leave a safety margin of 1MB to prevent overrunning the stack when
+    // pushing values (total stack size is 2MB).
+    stackLimit_ = reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
     pc_modified_ = false;
     icount_ = 0;
     break_count_ = 0;
     resume_pc_ = 0;
     break_pc_ = nullptr;
     break_instr_ = 0;
 
     // Set up architecture state.
@@ -1331,115 +1249,104 @@ Simulator::Simulator(SimulatorRuntime *s
     // access violation if the simulator ever tries to execute it.
     registers_[pc] = bad_ra;
     registers_[ra] = bad_ra;
 
     for (int i = 0; i < kNumExceptions; i++)
         exceptions[i] = 0;
 
     lastDebuggerInput_ = nullptr;
+
+    redirection_ = nullptr;
 }
 
 // When the generated code calls an external reference we need to catch that in
 // the simulator.  The external reference will be a function compiled for the
 // host architecture.  We need to call that function instead of trying to
 // execute it with the simulator.  We do that by redirecting the external
 // reference to a swi (software-interrupt) instruction that is handled by
 // the simulator.  We write the original destination of the jump just at a known
 // offset from the swi instruction so the simulator knows what to call.
 class Redirection
 {
-    friend class SimulatorRuntime;
+    friend class Simulator;
 
-    Redirection(void* nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
+    Redirection(void* nativeFunction, ABIFunctionType type, Simulator *sim)
       : nativeFunction_(nativeFunction),
         swiInstruction_(kCallRedirInstr),
         type_(type),
         next_(nullptr)
     {
-        next_ = srt->redirection();
+        next_ = sim->redirection();
 	if (Simulator::ICacheCheckingEnabled)
-	    FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
-        srt->setRedirection(this);
+	    FlushICache(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
+        sim->setRedirection(this);
     }
 
   public:
     void *addressOfSwiInstruction() { return &swiInstruction_; }
     void *nativeFunction() const { return nativeFunction_; }
     ABIFunctionType type() const { return type_; }
 
     static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
-        PerThreadData *pt = TlsPerThreadData.get();
-        SimulatorRuntime *srt = pt->simulatorRuntime();
-        AutoLockSimulatorRuntime alsr(srt);
-
-        MOZ_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
-
-        Redirection *current = srt->redirection();
+        Simulator *sim = Simulator::Current();
+        Redirection *current = sim->redirection();
         for (; current != nullptr; current = current->next_) {
             if (current->nativeFunction_ == nativeFunction) {
                 MOZ_ASSERT(current->type() == type);
                 return current;
             }
         }
 
         Redirection *redir = (Redirection *)js_malloc(sizeof(Redirection));
         if (!redir) {
             MOZ_ReportAssertionFailure("[unhandlable oom] Simulator redirection",
                                        __FILE__, __LINE__);
             MOZ_CRASH();
         }
-        new(redir) Redirection(nativeFunction, type, srt);
+        new(redir) Redirection(nativeFunction, type, sim);
         return redir;
     }
 
     static Redirection *FromSwiInstruction(SimInstruction *swiInstruction) {
         uint8_t *addrOfSwi = reinterpret_cast<uint8_t*>(swiInstruction);
         uint8_t *addrOfRedirection = addrOfSwi - offsetof(Redirection, swiInstruction_);
         return reinterpret_cast<Redirection*>(addrOfRedirection);
     }
 
   private:
     void *nativeFunction_;
     uint32_t swiInstruction_;
     ABIFunctionType type_;
     Redirection *next_;
 };
 
+Simulator::~Simulator()
+{
+    js_free(stack_);
+    Redirection *r = redirection_;
+    while (r) {
+        Redirection *next = r->next_;
+        js_delete(r);
+        r = next;
+    }
+}
+
 /* static */ void *
 Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
 {
     Redirection *redirection = Redirection::Get(nativeFunction, type);
     return redirection->addressOfSwiInstruction();
 }
 
-SimulatorRuntime::~SimulatorRuntime()
-{
-    Redirection *r = redirection_;
-    while (r) {
-        Redirection *next = r->next_;
-        js_delete(r);
-        r = next;
-    }
-    if (lock_)
-        PR_DestroyLock(lock_);
-}
-
 // Get the active Simulator for the current thread.
 Simulator *
 Simulator::Current()
 {
-    PerThreadData *pt = TlsPerThreadData.get();
-    Simulator *sim = pt->simulator();
-    if (!sim) {
-        sim = js_new<Simulator>(pt->simulatorRuntime());
-        pt->setSimulator(sim);
-    }
-
-    return sim;
+    return TlsPerThreadData.get()->simulator();
 }
 
 // Sets the register in the architecture state. It will also deal with updating
 // Simulator internal state for special registers such as PC.
 void Simulator::setRegister(int reg, int32_t value)
 {
     MOZ_ASSERT((reg >= 0) && (reg < Register::kNumSimuRegisters));
     if (reg == pc) {
@@ -1803,19 +1710,23 @@ Simulator::writeB(uint32_t addr, int8_t 
 {
     int8_t *ptr = reinterpret_cast<int8_t*>(addr);
     *ptr = value;
 }
 
 uintptr_t
 Simulator::stackLimit() const
 {
-    // Leave a safety margin of 1MB to prevent overrunning the stack when
-    // pushing values (total stack size is 2MB).
-    return reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
+    return stackLimit_;
+}
+
+uintptr_t *
+Simulator::addressOfStackLimit()
+{
+    return &stackLimit_;
 }
 
 bool
 Simulator::overRecursed(uintptr_t newsp) const
 {
     if (newsp == 0)
         newsp = getRegister(sp);
     return newsp <= stackLimit();
@@ -3297,20 +3208,18 @@ Simulator::decodeTypeJump(SimInstruction
     set_pc(next_pc);
     pc_modified_ = true;
 }
 
 // Executes the current instruction.
 void
 Simulator::instructionDecode(SimInstruction *instr)
 {
-    if (Simulator::ICacheCheckingEnabled) {
-        AutoLockSimulatorRuntime alsr(srt_);
-        CheckICache(srt_->icache(), instr);
-    }
+    if (Simulator::ICacheCheckingEnabled)
+        CheckICache(icache(), instr);
     pc_modified_ = false;
 
     switch (instr->instructionType()) {
       case SimInstruction::kRegisterType:
         decodeTypeRegister(instr);
         break;
       case SimInstruction::kImmediateType:
         decodeTypeImmediate(instr);
@@ -3511,45 +3420,14 @@ JSRuntime::simulator() const
 }
 
 js::jit::Simulator *
 js::PerThreadData::simulator() const
 {
     return runtime_->simulator();
 }
 
-void
-JSRuntime::setSimulator(js::jit::Simulator *sim)
-{
-    simulator_ = sim;
-    simulatorStackLimit_ = sim->stackLimit();
-}
-
-void
-js::PerThreadData::setSimulator(js::jit::Simulator *sim)
-{
-    runtime_->setSimulator(sim);
-}
-
 uintptr_t *
 JSRuntime::addressOfSimulatorStackLimit()
 {
-    return &simulatorStackLimit_;
-}
-
-js::jit::SimulatorRuntime *
-js::PerThreadData::simulatorRuntime() const
-{
-    return runtime_->simulatorRuntime();
+    return simulator_->addressOfStackLimit();
 }
 
-js::jit::SimulatorRuntime *
-JSRuntime::simulatorRuntime() const
-{
-    return simulatorRuntime_;
-}
-
-void
-JSRuntime::setSimulatorRuntime(js::jit::SimulatorRuntime *srt)
-{
-    MOZ_ASSERT(!simulatorRuntime_);
-    simulatorRuntime_ = srt;
-}
--- a/js/src/jit/mips/Simulator-mips.h
+++ b/js/src/jit/mips/Simulator-mips.h
@@ -31,19 +31,19 @@
 
 #ifdef JS_MIPS_SIMULATOR
 
 #include "jit/IonTypes.h"
 
 namespace js {
 namespace jit {
 
-class SimulatorRuntime;
-SimulatorRuntime *CreateSimulatorRuntime();
-void DestroySimulatorRuntime(SimulatorRuntime *srt);
+class Simulator;
+class Redirection;
+class CachePage;
 
 const intptr_t kPointerAlignment = 4;
 const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
 
 const intptr_t kDoubleAlignment = 8;
 const intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
 
 
@@ -132,27 +132,33 @@ class Simulator {
     enum FPURegister {
         f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11,
         f12, f13, f14, f15,   // f12 and f14 are arguments FPURegisters.
         f16, f17, f18, f19, f20, f21, f22, f23, f24, f25,
         f26, f27, f28, f29, f30, f31,
         kNumFPURegisters
     };
 
-    explicit Simulator(SimulatorRuntime *srt);
+    static Simulator *Create();
+    static void Destroy(Simulator *simulator);
+
+    // Constructor/destructor are for internal use only; use the static methods above.
+    Simulator();
     ~Simulator();
 
     // The currently executing Simulator instance. Potentially there can be one
     // for each native thread.
     static Simulator *Current();
 
     static inline uintptr_t StackLimit() {
         return Simulator::Current()->stackLimit();
     }
 
+    uintptr_t *addressOfStackLimit();
+
     // Accessors for register state. Reading the pc value adheres to the MIPS
     // architecture specification and is off by a 8 from the currently executing
     // instruction.
     void setRegister(int reg, int32_t value);
     int32_t getRegister(int reg) const;
     double getDoubleFromRegisterPair(int reg);
     // Same for FPURegisters.
     void setFpuRegister(int fpureg, int32_t value);
@@ -310,31 +316,30 @@ class Simulator {
     int32_t registers_[kNumSimuRegisters];
     // Coprocessor Registers.
     int32_t FPUregisters_[kNumFPURegisters];
     // FPU control register.
     uint32_t FCSR_;
 
     // Simulator support.
     char *stack_;
+    uintptr_t stackLimit_;
     bool pc_modified_;
     int icount_;
     int break_count_;
 
     int32_t resume_pc_;
 
     // Debugger input.
     char *lastDebuggerInput_;
 
     // Registered breakpoints.
     SimInstruction *break_pc_;
     Instr break_instr_;
 
-    SimulatorRuntime *srt_;
-
     // A stop is watched if its code is less than kNumOfWatchedStops.
     // Only watched stops support enabling/disabling and the counter feature.
     static const uint32_t kNumOfWatchedStops = 256;
 
 
     // Stop is disabled if bit 31 is set.
     static const uint32_t kStopDisabledBit = 1U << 31;
 
@@ -342,16 +347,46 @@ class Simulator {
     // instruction, if bit 31 of watchedStops_[code].count is unset.
     // The value watchedStops_[code].count & ~(1 << 31) indicates how many times
     // the breakpoint was hit or gone through.
     struct StopCountAndDesc {
         uint32_t count_;
         char *desc_;
     };
     StopCountAndDesc watchedStops_[kNumOfWatchedStops];
+
+  private:
+    Redirection *redirection_;
+
+    // ICache checking.
+    struct ICacheHasher {
+        typedef void *Key;
+        typedef void *Lookup;
+        static HashNumber hash(const Lookup &l);
+        static bool match(const Key &k, const Lookup &l);
+    };
+
+  public:
+    typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
+
+  protected:
+    ICacheMap icache_;
+
+  public:
+    ICacheMap &icache() {
+        return icache_;
+    }
+
+    Redirection *redirection() const {
+        return redirection_;
+    }
+
+    void setRedirection(js::jit::Redirection *redirection) {
+        redirection_ = redirection;
+    }
 };
 
 #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror)             \
     JS_BEGIN_MACRO                                                              \
         if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) {       \
             js_ReportOverRecursed(cx);                                          \
             onerror;                                                            \
         }                                                                       \
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1186,18 +1186,19 @@ JSContext::mark(JSTracer *trc)
         compartment_->mark();
 }
 
 void *
 ExclusiveContext::stackLimitAddressForJitCode(StackKind kind)
 {
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     return runtime_->addressOfSimulatorStackLimit();
+#else
+    return stackLimitAddress(kind);
 #endif
-    return stackLimitAddress(kind);
 }
 
 JSVersion
 JSContext::findVersion() const
 {
     if (JSScript *script = currentScript(nullptr, ALLOW_CROSS_COMPARTMENT))
         return script->getVersion();
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2320,17 +2320,17 @@ struct ArenasToUpdate
 {
     enum KindsToUpdate {
         FOREGROUND = 1,
         BACKGROUND = 2,
         ALL = FOREGROUND | BACKGROUND
     };
     ArenasToUpdate(JSRuntime *rt, KindsToUpdate kinds);
     bool done() { return initialized && arena == nullptr; }
-    ArenaHeader* next();
+    ArenaHeader* next(AutoLockHelperThreadState& lock);
     ArenaHeader *getArenasToUpdate(AutoLockHelperThreadState& lock, unsigned max);
 
   private:
     bool initialized;
     KindsToUpdate kinds;
     GCZonesIter zone;    // Current zone to process, unless zone.done()
     unsigned kind;       // Current alloc kind to process
     ArenaHeader *arena;  // Next arena to process
@@ -2344,30 +2344,30 @@ bool ArenasToUpdate::shouldProcessKind(u
     if (kind == FINALIZE_FAT_INLINE_STRING ||
         kind == FINALIZE_STRING ||
         kind == FINALIZE_EXTERNAL_STRING ||
         kind == FINALIZE_SYMBOL)
     {
         return false;
     }
 
-    if (kind > FINALIZE_OBJECT_LAST || js::gc::IsBackgroundFinalized(AllocKind(kind)))
+    if (js::gc::IsBackgroundFinalized(AllocKind(kind)))
         return (kinds & BACKGROUND) != 0;
     else
         return (kinds & FOREGROUND) != 0;
 }
 
 ArenasToUpdate::ArenasToUpdate(JSRuntime *rt, KindsToUpdate kinds)
   : initialized(false), kinds(kinds), zone(rt, SkipAtoms)
 {
     MOZ_ASSERT(kinds && !(kinds & ~ALL));
 }
 
 ArenaHeader *
-ArenasToUpdate::next()
+ArenasToUpdate::next(AutoLockHelperThreadState& lock)
 {
     // Find the next arena to update.
     //
     // Note that this uses a generator-like arrangement. The first time this is
     // called, |initialized| is false and the for-loops below are entered in the
     // normal way, returning the first arena found. In subsequent invocations we
     // jump directly into the body of the for loops just after the previous
     // return. All state is stored in class members and so preserved between
@@ -2402,17 +2402,17 @@ ArenasToUpdate::getArenasToUpdate(AutoLo
 {
     if (zone.done())
         return nullptr;
 
     ArenaHeader *head = nullptr;
     ArenaHeader *tail = nullptr;
 
     for (unsigned i = 0; i < count; ++i) {
-        ArenaHeader *arena = next();
+        ArenaHeader *arena = next(lock);
         if (!arena)
             break;
 
         if (tail)
             tail->setNextArenaToUpdate(arena);
         else
             head = arena;
         tail = arena;
@@ -2487,41 +2487,56 @@ UpdateCellPointersTask::run()
 
 void
 GCRuntime::updateAllCellPointersParallel(MovingTracer *trc)
 {
     AutoDisableProxyCheck noProxyCheck(rt); // These checks assert when run in parallel.
 
     const size_t minTasks = 2;
     const size_t maxTasks = 8;
-    unsigned taskCount = Min(Max(HelperThreadState().cpuCount / 2, minTasks) + 1,
-                             maxTasks);
-    UpdateCellPointersTask updateTasks[maxTasks];
+    size_t targetTaskCount = HelperThreadState().cpuCount / 2;
+    size_t taskCount = Min(Max(targetTaskCount, minTasks), maxTasks);
+    UpdateCellPointersTask bgTasks[maxTasks];
+    UpdateCellPointersTask fgTask;
 
     ArenasToUpdate fgArenas(rt, ArenasToUpdate::FOREGROUND);
     ArenasToUpdate bgArenas(rt, ArenasToUpdate::BACKGROUND);
-    AutoLockHelperThreadState lock;
-    unsigned i;
-    for (i = 0; i < taskCount && !bgArenas.done(); ++i) {
-        ArenasToUpdate *source = i == 0 ? &fgArenas : &bgArenas;
-        updateTasks[i].init(rt, source, lock);
-        startTask(updateTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
-    }
-    unsigned tasksStarted = i;
-
-    for (i = 0; i < tasksStarted; ++i)
-        joinTask(updateTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
+
+    unsigned tasksStarted = 0;
+    {
+        AutoLockHelperThreadState lock;
+        unsigned i;
+        for (i = 0; i < taskCount && !bgArenas.done(); ++i) {
+            bgTasks[i].init(rt, &bgArenas, lock);
+            startTask(bgTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
+        }
+        tasksStarted = i;
+
+        fgTask.init(rt, &fgArenas, lock);
+    }
+
+    fgTask.runFromMainThread(rt);
+
+    {
+        AutoLockHelperThreadState lock;
+        for (unsigned i = 0; i < tasksStarted; ++i)
+            joinTask(bgTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
+    }
 }
 
 void
 GCRuntime::updateAllCellPointersSerial(MovingTracer *trc)
 {
-    ArenasToUpdate allArenas(rt, ArenasToUpdate::ALL);
-    while (ArenaHeader *arena = allArenas.next())
-        UpdateCellPointers(trc, arena);
+    UpdateCellPointersTask task;
+    {
+        AutoLockHelperThreadState lock;
+        ArenasToUpdate allArenas(rt, ArenasToUpdate::ALL);
+        task.init(rt, &allArenas, lock);
+    }
+    task.runFromMainThread(rt);
 }
 
 /*
  * Update pointers to relocated cells by doing a full heap traversal and sweep.
  *
  * The latter is necessary to update weak references which are not marked as
  * part of the traversal.
  */
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -4381,16 +4381,19 @@ JSObject::splicePrototype(JSContext *cx,
      * can be rearranged as needed without destroying type information for
      * the old or new types.
      */
     MOZ_ASSERT(self->hasSingletonType());
 
     /* Inner objects may not appear on prototype chains. */
     MOZ_ASSERT_IF(proto.isObject(), !proto.toObject()->getClass()->ext.outerObject);
 
+    if (proto.isObject() && !proto.toObject()->setDelegate(cx))
+        return false;
+
     /*
      * Force type instantiation when splicing lazy types. This may fail,
      * in which case inference will be disabled for the compartment.
      */
     Rooted<TypeObject*> type(cx, self->getType(cx));
     if (!type)
         return false;
     Rooted<TypeObject*> protoType(cx, nullptr);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2699,47 +2699,55 @@ JSObject::fixupAfterMovingGC()
         }
     }
 }
 
 bool
 js::SetClassAndProto(JSContext *cx, HandleObject obj,
                      const Class *clasp, Handle<js::TaggedProto> proto)
 {
-    /*
-     * Regenerate shapes for all of the scopes along the old prototype chain,
-     * in case any entries were filled by looking up through obj. Stop when a
-     * non-native object is found, prototype lookups will not be cached across
-     * these.
-     *
-     * How this shape change is done is very delicate; the change can be made
-     * either by marking the object's prototype as uncacheable (such that the
-     * property cache and JIT'ed ICs cannot assume the shape determines the
-     * prototype) or by just generating a new shape for the object. Choosing
-     * the former is bad if the object is on the prototype chain of other
-     * objects, as the uncacheable prototype can inhibit iterator caches on
-     * those objects and slow down prototype accesses. Choosing the latter is
-     * bad if there are many similar objects to this one which will have their
-     * prototype mutated, as the generateOwnShape forces the object into
-     * dictionary mode and similar property lineages will be repeatedly cloned.
-     *
-     * :XXX: bug 707717 make this code less brittle.
-     */
+    // Regenerate the object's shape. If the object is a proto (isDelegate()),
+    // we also need to regenerate shapes for all of the objects along the old
+    // prototype chain, in case any entries were filled by looking up through
+    // obj. Stop when a non-native object is found, prototype lookups will not
+    // be cached across these.
+    //
+    // How this shape change is done is very delicate; the change can be made
+    // either by marking the object's prototype as uncacheable (such that the
+    // JIT'ed ICs cannot assume the shape determines the prototype) or by just
+    // generating a new shape for the object. Choosing the former is bad if the
+    // object is on the prototype chain of other objects, as the uncacheable
+    // prototype can inhibit iterator caches on those objects and slow down
+    // prototype accesses. Choosing the latter is bad if there are many similar
+    // objects to this one which will have their prototype mutated, as the
+    // generateOwnShape forces the object into dictionary mode and similar
+    // property lineages will be repeatedly cloned.
+    //
+    // :XXX: bug 707717 make this code less brittle.
     RootedObject oldproto(cx, obj);
     while (oldproto && oldproto->isNative()) {
         if (oldproto->hasSingletonType()) {
             if (!oldproto->as<NativeObject>().generateOwnShape(cx))
                 return false;
         } else {
             if (!oldproto->setUncacheableProto(cx))
                 return false;
         }
+        if (!obj->isDelegate()) {
+            // If |obj| is not a proto of another object, we don't need to
+            // reshape the whole proto chain.
+            MOZ_ASSERT(obj == oldproto);
+            break;
+        }
         oldproto = oldproto->getProto();
     }
 
+    if (proto.isObject() && !proto.toObject()->setDelegate(cx))
+        return false;
+
     if (obj->hasSingletonType()) {
         /*
          * Just splice the prototype, but mark the properties as unknown for
          * consistent behavior.
          */
         if (!obj->splicePrototype(cx, clasp, proto))
             return false;
         MarkTypeObjectUnknownProperties(cx, obj->type());
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -360,17 +360,19 @@ class JSObject : public js::gc::Cell
     }
 
     bool hasTenuredProto() const;
 
     bool uninlinedIsProxy() const;
 
     JSObject *getProto() const {
         MOZ_ASSERT(!uninlinedIsProxy());
-        return getTaggedProto().toObjectOrNull();
+        JSObject *proto = getTaggedProto().toObjectOrNull();
+        MOZ_ASSERT_IF(proto && proto->isNative(), proto->isDelegate());
+        return proto;
     }
 
     // Normal objects and a subset of proxies have uninteresting [[Prototype]].
     // For such objects the [[Prototype]] is just a value returned when needed
     // for accesses, or modified in response to requests.  These objects store
     // the [[Prototype]] directly within |obj->type_|.
     //
     // Proxies that don't have such a simple [[Prototype]] instead have a
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -153,18 +153,16 @@ JSRuntime::JSRuntime(JSRuntime *parentRu
 #ifdef DEBUG
     checkRequestDepth(0),
     activeContext(nullptr),
 #endif
     gc(thisFromCtor()),
     gcInitialized(false),
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     simulator_(nullptr),
-    simulatorStackLimit_(0),
-    simulatorRuntime_(nullptr),
 #endif
     scriptAndCountsVector(nullptr),
     NaNValue(DoubleNaNValue()),
     negativeInfinityValue(DoubleValue(NegativeInfinity<double>())),
     positiveInfinityValue(DoubleValue(PositiveInfinity<double>())),
     emptyString(nullptr),
 #ifdef NIGHTLY_BUILD
     assertOnScriptEntryHook_(nullptr),
@@ -313,18 +311,18 @@ JSRuntime::init(uint32_t maxbytes, uint3
     gcInitialized = true;
 
     if (!InitRuntimeNumberState(this))
         return false;
 
     dateTimeInfo.updateTimeZoneAdjustment();
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
-    simulatorRuntime_ = js::jit::CreateSimulatorRuntime();
-    if (!simulatorRuntime_)
+    simulator_ = js::jit::Simulator::Create();
+    if (!simulator_)
         return false;
 #endif
 
     jitSupportsFloatingPoint = js::jit::JitSupportsFloatingPoint();
     jitSupportsSimd = js::jit::JitSupportsSimd();
 
     signalHandlersInstalled_ = EnsureSignalHandlersInstalled(this);
     canUseSignalHandlers_ = signalHandlersInstalled_ && !SignalBasedTriggersDisabled();
@@ -430,18 +428,17 @@ JSRuntime::~JSRuntime()
     js_delete(execAlloc_);  /* Delete after jitRuntime_. */
 
     js_delete(ionPcScriptCache);
 
     gc.storeBuffer.disable();
     gc.nursery.disable();
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
-    js::jit::DestroySimulatorRuntime(simulatorRuntime_);
-    js_delete(simulator_);
+    js::jit::Simulator::Destroy(simulator_);
 #endif
 
     DebugOnly<size_t> oldCount = liveRuntimesCount--;
     MOZ_ASSERT(oldCount > 0);
 
     js::TlsPerThreadData.set(nullptr);
 
 #ifdef XP_WIN
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -80,17 +80,16 @@ class AsmJSActivation;
 class AsmJSModule;
 class MathCache;
 
 namespace jit {
 class JitRuntime;
 class JitActivation;
 struct PcScriptCache;
 class Simulator;
-class SimulatorRuntime;
 struct AutoFlushICache;
 class CompileRuntime;
 }
 
 /*
  * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
  * given pc in a script. We use the script->code pointer to tag the cache,
  * instead of the script address itself, so that source notes are always found
@@ -557,18 +556,16 @@ class PerThreadData : public PerThreadDa
         }
     };
 
     js::jit::AutoFlushICache *autoFlushICache() const;
     void setAutoFlushICache(js::jit::AutoFlushICache *afc);
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::Simulator *simulator() const;
-    void setSimulator(js::jit::Simulator *sim);
-    js::jit::SimulatorRuntime *simulatorRuntime() const;
 #endif
 };
 
 class AutoLockForExclusiveAccess;
 
 } // namespace js
 
 struct JSRuntime : public JS::shadow::Runtime,
@@ -954,31 +951,26 @@ struct JSRuntime : public JS::shadow::Ru
     }
 
     void unlockGC() {
         gc.unlockGC();
     }
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::Simulator *simulator_;
-    uintptr_t simulatorStackLimit_;
-    js::jit::SimulatorRuntime *simulatorRuntime_;
 #endif
 
   public:
     void setNeedsIncrementalBarrier(bool needs) {
         needsIncrementalBarrier_ = needs;
     }
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::Simulator *simulator() const;
-    void setSimulator(js::jit::Simulator *sim);
     uintptr_t *addressOfSimulatorStackLimit();
-    js::jit::SimulatorRuntime *simulatorRuntime() const;
-    void setSimulatorRuntime(js::jit::SimulatorRuntime *srt);
 #endif
 
     /* Strong references on scripts held for PCCount profiling API. */
     js::ScriptAndCountsVector *scriptAndCountsVector;
 
     /* Well-known numbers held for use by this runtime's contexts. */
     const js::Value     NaNValue;
     const js::Value     negativeInfinityValue;
--- a/layout/base/TouchCaret.cpp
+++ b/layout/base/TouchCaret.cpp
@@ -453,17 +453,18 @@ TouchCaret::IsDisplayable()
   }
 
   if (!nsContentUtils::HasNonEmptyTextContent(
          editingHost, nsContentUtils::eRecurseIntoChildren)) {
     TOUCHCARET_LOG("The content is empty!");
     return false;
   }
 
-  if (!nsLayoutUtils::IsRectVisibleInScrollFrames(focusFrame, focusRect)) {
+  if (mState != TOUCHCARET_TOUCHDRAG_ACTIVE &&
+        !nsLayoutUtils::IsRectVisibleInScrollFrames(focusFrame, focusRect)) {
     TOUCHCARET_LOG("Caret does not show in the scrollable frame!");
     return false;
   }
 
   TOUCHCARET_LOG("Touch caret is displayable!");
   return true;
 }
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -309,23 +309,38 @@ private:
   // and is shutdown when the RefreshDriverTimer is deleted. The alternative is
   // to (a) make all RefreshDriverTimer RefCounted or (b) use different
   // VsyncObserver types.
   class RefreshDriverVsyncObserver MOZ_FINAL : public VsyncObserver
   {
   public:
     explicit RefreshDriverVsyncObserver(VsyncRefreshDriverTimer* aVsyncRefreshDriverTimer)
       : mVsyncRefreshDriverTimer(aVsyncRefreshDriverTimer)
+      , mRefreshTickLock("RefreshTickLock")
+      , mProcessedVsync(true)
     {
       MOZ_ASSERT(NS_IsMainThread());
     }
 
     virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) MOZ_OVERRIDE
     {
       if (!NS_IsMainThread()) {
+        MOZ_ASSERT(XRE_IsParentProcess());
+        // Compress vsync notifications such that only 1 may run at a time
+        // This is so that we don't flood the refresh driver with vsync messages
+        // if the main thread is blocked for long periods of time
+        { // scope lock
+          MonitorAutoLock lock(mRefreshTickLock);
+          mRecentVsync = aVsyncTimestamp;
+          if (!mProcessedVsync) {
+            return true;
+          }
+          mProcessedVsync = false;
+        }
+
         nsCOMPtr<nsIRunnable> vsyncEvent =
              NS_NewRunnableMethodWithArg<TimeStamp>(this,
                                                     &RefreshDriverVsyncObserver::TickRefreshDriver,
                                                     aVsyncTimestamp);
         NS_DispatchToMainThread(vsyncEvent);
       } else {
         TickRefreshDriver(aVsyncTimestamp);
       }
@@ -341,28 +356,37 @@ private:
 
   private:
     virtual ~RefreshDriverVsyncObserver() {}
 
     void TickRefreshDriver(TimeStamp aVsyncTimestamp)
     {
       MOZ_ASSERT(NS_IsMainThread());
 
+      if (XRE_IsParentProcess()) {
+        MonitorAutoLock lock(mRefreshTickLock);
+        aVsyncTimestamp = mRecentVsync;
+        mProcessedVsync = true;
+      }
+
       // We might have a problem that we call ~VsyncRefreshDriverTimer() before
       // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer
       // before use.
       if (mVsyncRefreshDriverTimer) {
         mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp);
       }
     }
 
     // VsyncRefreshDriverTimer holds this RefreshDriverVsyncObserver and it will
     // be always available before Shutdown(). We can just use the raw pointer
     // here.
     VsyncRefreshDriverTimer* mVsyncRefreshDriverTimer;
+    Monitor mRefreshTickLock;
+    TimeStamp mRecentVsync;
+    bool mProcessedVsync;
   }; // RefreshDriverVsyncObserver
 
   virtual ~VsyncRefreshDriverTimer()
   {
     if (XRE_IsParentProcess()) {
       mVsyncDispatcher->SetParentRefreshTimer(nullptr);
       mVsyncDispatcher = nullptr;
     } else {
@@ -411,19 +435,23 @@ private:
   void RunRefreshDrivers(TimeStamp aTimeStamp)
   {
     int64_t jsnow = JS_Now();
     TimeDuration diff = TimeStamp::Now() - aTimeStamp;
     int64_t vsyncJsNow = jsnow - diff.ToMicroseconds();
     Tick(vsyncJsNow, aTimeStamp);
   }
 
+  nsRefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
+  // Used for parent process.
   nsRefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher;
-  nsRefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
-  VsyncChild* mVsyncChild;
+  // Used for child process.
+  // The mVsyncChild will be always available before VsncChild::ActorDestroy().
+  // After ActorDestroy(), StartTimer() and StopTimer() calls will be non-op.
+  nsRefPtr<VsyncChild> mVsyncChild;
 }; // VsyncRefreshDriverTimer
 
 /*
  * PreciseRefreshDriverTimer schedules ticks based on the current time
  * and when the next tick -should- be sent if we were hitting our
  * rate.  It always schedules ticks on multiples of aRate -- meaning that
  * if some execution takes longer than an alloted slot, the next tick
  * will be delayed instead of triggering instantly.  This might not be
--- a/layout/ipc/PVsync.ipdl
+++ b/layout/ipc/PVsync.ipdl
@@ -16,17 +16,17 @@ namespace layout {
  * interfaces for content to observe/unobserve vsync event notifications.
  */
 async protocol PVsync
 {
   manager PBackground;
 
 child:
   // Send vsync event from chrome to content process.
-  async Notify(TimeStamp aVsyncTimestamp);
+  async Notify(TimeStamp aVsyncTimestamp) compress;
 
 parent:
   // Content process use these messages to acquire the vsync event.
   async Observe();
   async Unobserve();
 
   // This message is never sent. Each PVsync actor will stay alive as long as
   // its PBackground manager.
--- a/layout/ipc/VsyncChild.cpp
+++ b/layout/ipc/VsyncChild.cpp
@@ -8,58 +8,62 @@
 #include "mozilla/VsyncDispatcher.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace layout {
 
 VsyncChild::VsyncChild()
   : mObservingVsync(false)
+  , mIsShutdown(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 VsyncChild::~VsyncChild()
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 bool
 VsyncChild::SendObserve()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!mObservingVsync) {
+  if (!mObservingVsync && !mIsShutdown) {
+    mObservingVsync = true;
     PVsyncChild::SendObserve();
-    mObservingVsync = true;
   }
   return true;
 }
 
 bool
 VsyncChild::SendUnobserve()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (mObservingVsync) {
+  if (mObservingVsync && !mIsShutdown) {
+    mObservingVsync = false;
     PVsyncChild::SendUnobserve();
-    mObservingVsync = false;
   }
   return true;
 }
 
 void
 VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mIsShutdown);
+  mIsShutdown = true;
   mObserver = nullptr;
 }
 
 bool
 VsyncChild::RecvNotify(const TimeStamp& aVsyncTimestamp)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mIsShutdown);
   if (mObservingVsync && mObserver) {
     mObserver->NotifyVsync(aVsyncTimestamp);
   }
   return true;
 }
 
 void
 VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver)
--- a/layout/ipc/VsyncChild.h
+++ b/layout/ipc/VsyncChild.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layout_ipc_VsyncChild_h
 #define mozilla_layout_ipc_VsyncChild_h
 
 #include "mozilla/layout/PVsyncChild.h"
+#include "nsISupportsImpl.h"
 #include "nsRefPtr.h"
 
 namespace mozilla {
 
 class VsyncObserver;
 
 namespace ipc {
 class BackgroundChildImpl;
@@ -20,16 +21,18 @@ class BackgroundChildImpl;
 namespace layout {
 
 // The PVsyncChild actor receives a vsync event from the main process and
 // delivers it to the child process. Currently this is restricted to the main
 // thread only. The actor will stay alive until the process dies or its
 // PVsyncParent actor dies.
 class VsyncChild MOZ_FINAL : public PVsyncChild
 {
+  NS_INLINE_DECL_REFCOUNTING(VsyncChild)
+
   friend class mozilla::ipc::BackgroundChildImpl;
 
 public:
   // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
   // mObservingVsync to handle the race problem of unobserving vsync event.
   bool SendObserve();
   bool SendUnobserve();
 
@@ -39,16 +42,17 @@ public:
 private:
   VsyncChild();
   virtual ~VsyncChild();
 
   virtual bool RecvNotify(const TimeStamp& aVsyncTimestamp) MOZ_OVERRIDE;
   virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) MOZ_OVERRIDE;
 
   bool mObservingVsync;
+  bool mIsShutdown;
 
   // The content side vsync observer.
   nsRefPtr<VsyncObserver> mObserver;
 };
 
 } // namespace layout
 } // namespatce mozilla
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1127107-1-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    div.test {
+      /* Author expects this to prevent wrapping, and may add
+         "overflow:hidden;text-overflow:ellipsis" for nice effect: */
+      white-space: nowrap;
+
+      width: 200px;
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+  <div class="test">
+    Does this text wrap? Does this text wrap? Does this text wrap?
+    Does this text wrap?
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1127107-1a-nowrap.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    div.test {
+      /* Author expects this to prevent wrapping, and may add
+         "overflow:hidden;text-overflow:ellipsis" for nice effect: */
+      white-space: nowrap;
+
+      /* BUT these (combined) seem to allow wrapping: */
+      -moz-hyphens: auto;
+      -ms-hyphens: auto;
+      -webkit-hyphens: auto;
+      hyphens: auto;
+      word-break: break-all;
+
+      width: 200px;
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+  <div class="test">
+    Does this text wrap? Does this text wrap? Does this text wrap?
+    Does this text wrap?
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1127107-1b-pre.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    div.test {
+      /* Author expects this to prevent wrapping, and may add
+         "overflow:hidden;text-overflow:ellipsis" for nice effect: */
+      white-space: pre;
+
+      /* BUT these (combined) seem to allow wrapping: */
+      -moz-hyphens: auto;
+      -ms-hyphens: auto;
+      -webkit-hyphens: auto;
+      hyphens: auto;
+      word-break: break-all;
+
+      width: 200px;
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+  <div class="test">Does this text wrap? Does this text wrap? Does this text wrap? Does this text wrap?</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1127107-2-capitalize-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    div.test {
+      /* Author expects this to prevent wrapping, and may add
+         "overflow:hidden;text-overflow:ellipsis" for nice effect: */
+      white-space: nowrap;
+
+      width: 200px;
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+  <div class="test">
+    Does This Text Wrap? Does This Text Wrap? Does This Text Wrap?
+    Does This Text Wrap?
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1127107-2-capitalize.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    div.test {
+      /* Author expects this to prevent wrapping, and may add
+         "overflow:hidden;text-overflow:ellipsis" for nice effect: */
+      white-space: nowrap;
+
+      /* BUT these (combined) seem to allow wrapping: */
+      text-transform: capitalize;
+      word-break: break-all;
+
+      width: 200px;
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+  <div class="test">
+    Does this text wrap? Does this text wrap? Does this text wrap?
+    Does this text wrap?
+  </div>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1853,8 +1853,11 @@ fuzzy-if(winWidget&&!layersGPUAccelerate
 == 1103258-1.html 1103258-1-ref.html # assertion crash test with layers culling test
 == 1105137-1.html 1105137-1-ref.html
 fuzzy-if(d2d,36,304) HTTP(..) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
 == 1111753-1.html about:blank
 == 1119117-1a.html 1119117-1-ref.html
 == 1119117-1b.html 1119117-1-ref.html
 == 1120431-1.html 1120431-1-ref.html
 == 1120431-2.html 1120431-2-ref.html
+== 1127107-1a-nowrap.html 1127107-1-ref.html
+== 1127107-1b-pre.html 1127107-1-ref.html
+== 1127107-2-capitalize.html 1127107-2-capitalize-ref.html
--- a/layout/reftests/css-ruby/dynamic-removal-3-ref.html
+++ b/layout/reftests/css-ruby/dynamic-removal-3-ref.html
@@ -15,12 +15,12 @@
   <p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
 
   <p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
   <p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
 
   <p>'ab' should be paried with 'xy':</p>
 
   <p><rbc>ab</rbc><rt>xy</rt></p>
-  <p><rb>ab</rb><rtc>xy</rtc></p>
+  <p><rb>ab</rb><rtc style="letter-spacing: 1px">xy</rtc></p>
 
 </body>
 </html>
--- a/layout/reftests/css-ruby/dynamic-removal-3.html
+++ b/layout/reftests/css-ruby/dynamic-removal-3.html
@@ -25,12 +25,13 @@
   <p><rb>a</rb><rb>b</rb><rt class="remove-after">x</rt> <rt>y</rt></p>
 
   <p>'ab' should be paried with 'xy':</p>
 
   <!-- merge -->
   <!--     pseudo ruby base -->
   <p><rbc>a<rb class="remove"></rb>b</rbc><rt>xy</rt></p>
   <!--     pseudo ruby text -->
-  <p><rb>ab</rb><rtc>x<rt class="remove"></rt>y</rtc></p>
+  <!-- letter-spacing is added here to avoid fuzzy on Windows. See bug 1111891 -->
+  <p><rb>ab</rb><rtc style="letter-spacing: 1px">x<rt class="remove"></rt>y</rtc></p>
 
 </body>
 </html>
--- a/layout/reftests/css-ruby/reftest.list
+++ b/layout/reftests/css-ruby/reftest.list
@@ -12,17 +12,17 @@ fails == autohiding-3.html autohiding-3-
 == box-properties-2.html box-properties-2-ref.html
 == box-properties-3.html box-properties-3-ref.html
 == box-properties-4.html box-properties-4-ref.html
 == dynamic-insertion-1.html dynamic-insertion-1-ref.html
 == dynamic-insertion-2.html dynamic-insertion-2-ref.html
 == dynamic-insertion-3.html dynamic-insertion-3-ref.html
 == dynamic-removal-1.html dynamic-removal-1-ref.html
 == dynamic-removal-2.html dynamic-removal-2-ref.html
-fuzzy-if(winWidget,35,1) == dynamic-removal-3.html dynamic-removal-3-ref.html # bug 1111891
+== dynamic-removal-3.html dynamic-removal-3-ref.html
 == float-handling.html float-handling-ref.html
 == inlinize-blocks-1.html inlinize-blocks-1-ref.html
 == inlinize-blocks-2.html inlinize-blocks-2-ref.html
 == inlinize-blocks-3.html inlinize-blocks-3-ref.html
 == inlinize-blocks-4.html inlinize-blocks-4-ref.html
 == inlinize-blocks-5.html inlinize-blocks-5-ref.html
 == intra-level-whitespace-1.html intra-level-whitespace-1-ref.html
 == intra-level-whitespace-2.html intra-level-whitespace-2-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-transformed-child-01-ref.svg
@@ -0,0 +1,8 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect x="50" y="75" width="100" height="50" fill="blue"/>
+</svg>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-transformed-child-01.svg
@@ -0,0 +1,11 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
+    <rect x="0.25" y="0" width="0.5" height="1" fill="white" transform="rotate(90,0.5,0.5)"/>
+  </mask>
+  <rect x="50" y="50" width="100" height="100" fill="blue" mask="url(#mask)"/>
+</svg>
+
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -204,16 +204,17 @@ pref(svg.marker-improvements.enabled,tru
 == mask-basic-01.svg pass.svg
 == mask-basic-02.svg mask-basic-02-ref.svg
 == mask-basic-03.svg pass.svg
 == mask-basic-04.svg pass.svg
 == mask-extref-dataURI-01.svg pass.svg
 == mask-containing-masked-content-01.svg pass.svg
 == mask-transformed-01.svg mask-transformed-01-ref.svg
 == mask-transformed-02.svg pass.svg
+== mask-transformed-child-01.svg mask-transformed-child-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d,1,6400) == mask-type-01.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d,1,6400) == mask-type-02.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d,1,6400) == mask-type-03.svg mask-type-01-ref.svg
 pref(layout.css.masking.enabled,true) fuzzy-if(d2d,1,6400) == mask-type-04.svg mask-type-01-ref.svg
 == nested-viewBox-01.svg pass.svg
 == nesting-invalid-01.svg nesting-invalid-01-ref.svg
 fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),1,168) fuzzy-if(azureQuartz,1,122) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
 fuzzy-if(Android||B2G,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -272,17 +272,17 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(gf
     if (SVGFrame) {
       SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
     }
     gfxMatrix m = mMatrixForChildren;
     if (kid->GetContent()->IsSVG()) {
       m = static_cast<nsSVGElement*>(kid->GetContent())->
             PrependLocalTransformsTo(m);
     }
-    nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, mMatrixForChildren);
+    nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m);
   }
 
   RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
   if (!maskSnapshot) {
     return nullptr;
   }
   RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
   DataSourceSurface::MappedSurface map;
--- a/media/libopus/moz.build
+++ b/media/libopus/moz.build
@@ -77,16 +77,18 @@ if CONFIG['MOZ_SAMPLE_TYPE_FLOAT32']:
     ]
     SOURCES += silk_sources_float
     SOURCES += opus_sources_float
 else:
     LOCAL_INCLUDES += [
         'silk/fixed',
     ]
     SOURCES += silk_sources_fixed
+# for webrtc
+    SOURCES += opus_sources_float
 
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_AS']:
     SOURCES += celt_sources_arm
     GENERATED_SOURCES += [ '%s.%s' % (f, CONFIG['ASM_SUFFIX']) for f in [
         'celt_pitch_xcorr_arm-gnu',
     ]]
     # -Os is significantly slower, enable -O3 unless optimization is disabled
     if CONFIG['MOZ_OPTIMIZE']:
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
@@ -252,17 +252,20 @@ status_t SampleTable::setSampleToChunkPa
     for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
         uint8_t buffer[12];
         if (mDataSource->readAt(
                     mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
                 != (ssize_t)sizeof(buffer)) {
             return ERROR_IO;
         }
 
-        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
+        if (!U32_AT(buffer)) {
+          ALOGE("error reading sample to chunk table");
+          return ERROR_MALFORMED;  // chunk index is 1 based in the spec.
+        }
 
         // We want the chunk index to be 0-based.
         mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
         mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
         mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
     }
 
     return OK;
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -8,17 +8,17 @@ include('/build/gyp.mozbuild')
 
 webrtc_non_unified_sources = [
     'trunk/webrtc/common_audio/vad/vad_core.c',                                  # Because of name clash in the kInitCheck variable
     'trunk/webrtc/common_audio/vad/webrtc_vad.c',                                # Because of name clash in the kInitCheck variable
     'trunk/webrtc/modules/audio_coding/codecs/g722/g722_decode.c',               # Because of name clash in the saturate function
     'trunk/webrtc/modules/audio_coding/codecs/g722/g722_encode.c',               # Because of name clash in the saturate function
     'trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c',   # Because of name clash in the kDampFilter variable
     'trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c', # Because of name clash in the kDampFilter variable
-    'trunk/webrtc/modules/audio_coding/neteq4/audio_vector.cc',                  # Because of explicit template specializations
+    'trunk/webrtc/modules/audio_coding/neteq/audio_vector.cc',                   # Because of explicit template specializations
     'trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc',       # Because of LATE()
     'trunk/webrtc/modules/audio_device/linux/audio_mixer_manager_pulse_linux.cc',# Because of LATE()
     'trunk/webrtc/modules/audio_device/opensl/opensles_input.cc',                # Because of name clash in the kOption variable
     'trunk/webrtc/modules/audio_device/opensl/opensles_output.cc',               # Because of name clash in the kOption variable
     'trunk/webrtc/modules/audio_device/opensl/single_rw_fifo.cc',                # Because of name clash with #define FF
     'trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc',            # Because of ordering assumptions in strsafe.h
     'trunk/webrtc/modules/audio_processing/aec/aec_core.c',                      # Because of name clash in the ComfortNoise function
     'trunk/webrtc/modules/audio_processing/aecm/aecm_core.c',                    # Because of name clash in the ComfortNoise function
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -46,20 +46,16 @@
         './src/mediapipeline',
         './src/peerconnection',
         './src/sdp/sipcc',
         '../../../xpcom/base',
         '../../../dom/base',
         '../../../dom/media',
         '../../../media/mtransport',
         '../trunk',
-        '../trunk/webrtc',
-        '../trunk/webrtc/video_engine/include',
-        '../trunk/webrtc/voice_engine/include',
-        '../trunk/webrtc/modules/interface',
         '../../libyuv/include',
         '../../mtransport/third_party/nrappkit/src/util/libekr',
       ],
 
       #
       # DEPENDENCIES
       #
       'dependencies': [
@@ -204,17 +200,16 @@
         }],
         ['moz_webrtc_omx==1', {
           'sources': [
             './src/media-conduit/WebrtcOMXH264VideoCodec.cpp',
             './src/media-conduit/OMXVideoCodec.cpp',
           ],
           'include_dirs': [
             # hack on hack to re-add it after SrtpFlow removes it
-            '../../webrtc/trunk/webrtc',
             '../../../dom/media/omx',
             '../../../gfx/layers/client',
           ],
           'cflags_mozilla': [
             '-I$(ANDROID_SOURCE)/frameworks/av/include/media/stagefright',
             '-I$(ANDROID_SOURCE)/frameworks/av/include',
             '-I$(ANDROID_SOURCE)/frameworks/native/include/media/openmax',
             '-I$(ANDROID_SOURCE)/frameworks/native/include',
@@ -245,16 +240,17 @@
         }],
         ['(OS=="linux") or (OS=="android")', {
           'include_dirs': [
           ],
 
           'defines': [
             'OS_LINUX',
             'SIP_OS_LINUX',
+            'WEBRTC_POSIX',
             '_GNU_SOURCE',
             'LINUX',
             'GIPS_VER=3510',
             'SECLIB_OPENSSL',
           ],
 
           'cflags_mozilla': [
           ],
@@ -281,28 +277,30 @@
           'cflags_mozilla': [
           ],
         }],
         ['os_bsd==1', {
           'include_dirs': [
           ],
           'defines': [
             # avoiding pointless ifdef churn
+            'WEBRTC_POSIX',
             'SIP_OS_OSX',
             'OSX',
             'SECLIB_OPENSSL',
           ],
 
           'cflags_mozilla': [
           ],
         }],
         ['OS=="mac"', {
           'include_dirs': [
           ],
           'defines': [
+            'WEBRTC_POSIX',
             'OS_MACOSX',
             'SIP_OS_OSX',
             'OSX',
             '_FORTIFY_SOURCE=2',
           ],
 
           'cflags_mozilla': [
           ],
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -539,19 +539,19 @@ WebrtcAudioConduit::ConfigureRecvMediaCo
   DumpCodecDB();
   return kMediaConduitNoError;
 }
 MediaConduitErrorCode
 WebrtcAudioConduit::EnableAudioLevelExtension(bool enabled, uint8_t id)
 {
   CSFLogDebug(logTag,  "%s %d %d ", __FUNCTION__, enabled, id);
 
-  if (mPtrVoERTP_RTCP->SetRTPAudioLevelIndicationStatus(mChannel, enabled, id) == -1)
+  if (mPtrVoERTP_RTCP->SetSendAudioLevelIndicationStatus(mChannel, enabled, id) == -1)
   {
-    CSFLogError(logTag, "%s SetRTPAudioLevelIndicationStatus Failed", __FUNCTION__);
+    CSFLogError(logTag, "%s SetSendAudioLevelIndicationStatus Failed", __FUNCTION__);
     return kMediaConduitUnknownError;
   }
 
   return kMediaConduitNoError;
 }
 
 MediaConduitErrorCode
 WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -229,17 +229,18 @@ public:
 class VideoSessionConduit : public MediaSessionConduit
 {
 public:
   /**
    * Factory function to create and initialize a Video Conduit Session
    * return: Concrete VideoSessionConduitObject or nullptr in the case
    *         of failure
    */
-  static RefPtr<VideoSessionConduit> Create(VideoSessionConduit *aOther);
+  static RefPtr<VideoSessionConduit> Create(VideoSessionConduit *aOther,
+                                            bool receiving);
 
   enum FrameRequestType
   {
     FrameRequestNone,
     FrameRequestFir,
     FrameRequestPli,
     FrameRequestUnknown
   };
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -37,23 +37,25 @@ namespace mozilla {
 static const char* logTag ="WebrtcVideoSessionConduit";
 
 // 32 bytes is what WebRTC CodecInst expects
 const unsigned int WebrtcVideoConduit::CODEC_PLNAME_SIZE = 32;
 
 /**
  * Factory Method for VideoConduit
  */
-mozilla::RefPtr<VideoSessionConduit> VideoSessionConduit::Create(VideoSessionConduit *aOther)
+mozilla::RefPtr<VideoSessionConduit>
+VideoSessionConduit::Create(VideoSessionConduit *aOther,
+                            bool receiving)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   CSFLogDebug(logTag,  "%s ", __FUNCTION__);
 
   WebrtcVideoConduit* obj = new WebrtcVideoConduit();
-  if(obj->Init(static_cast<WebrtcVideoConduit*>(aOther)) != kMediaConduitNoError)
+  if(obj->Init(static_cast<WebrtcVideoConduit*>(aOther), receiving) != kMediaConduitNoError)
   {
     CSFLogError(logTag,  "%s VideoConduit Init Failed ", __FUNCTION__);
     delete obj;
     return nullptr;
   }
   CSFLogDebug(logTag,  "%s Successfully created VideoConduit ", __FUNCTION__);
   return obj;
 }
@@ -279,17 +281,19 @@ bool WebrtcVideoConduit::GetRTCPSenderRe
     *bytesSent = senderInfo.sender_octet_count;
   }
   return result;
 }
 
 /**
  * Performs initialization of the MANDATORY components of the Video Engine
  */
-MediaConduitErrorCode WebrtcVideoConduit::Init(WebrtcVideoConduit *other)
+MediaConduitErrorCode
+WebrtcVideoConduit::Init(WebrtcVideoConduit *other,
+                         bool receiving)
 {
   CSFLogDebug(logTag,  "%s this=%p other=%p", __FUNCTION__, this, other);
 
 #ifdef MOZILLA_INTERNAL_API
   // already know we must be on MainThread barring unit test weirdness
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
@@ -327,29 +331,29 @@ MediaConduitErrorCode WebrtcVideoConduit
     MOZ_ASSERT(!other->mOtherDirection);
     other->mOtherDirection = this;
     mOtherDirection = other;
 
     // only one can call ::Create()/GetVideoEngine()
     MOZ_ASSERT(other->mVideoEngine);
     mVideoEngine = other->mVideoEngine;
   } else {
-
 #ifdef MOZ_WIDGET_ANDROID
     // get the JVM
     JavaVM *jvm = jsjni_GetVM();
 
     if (webrtc::VideoEngine::SetAndroidObjects(jvm) != 0) {
       CSFLogError(logTag,  "%s: could not set Android objects", __FUNCTION__);
       return kMediaConduitSessionNotInited;
     }
 #endif
 
     // Per WebRTC APIs below function calls return nullptr on failure
-    if( !(mVideoEngine = webrtc::VideoEngine::Create()) )
+    mVideoEngine = webrtc::VideoEngine::Create();
+    if(!mVideoEngine)
     {
       CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
       return kMediaConduitSessionNotInited;
     }
 
     EnableWebRtcLog();
   }
 
@@ -440,40 +444,41 @@ MediaConduitErrorCode WebrtcVideoConduit
     }
 
     if(mPtrViECapture->ConnectCaptureDevice(mCapId,mChannel) == -1)
     {
       CSFLogError(logTag, "%s Unable to Connect capture module: %d ",
                   __FUNCTION__,mPtrViEBase->LastError());
       return kMediaConduitCaptureError;
     }
-
-    if(mPtrViERender->AddRenderer(mChannel,
-                                  webrtc::kVideoI420,
-                                  (webrtc::ExternalRenderer*) this) == -1)
-    {
-      CSFLogError(logTag, "%s Failed to added external renderer ", __FUNCTION__);
-      return kMediaConduitInvalidRenderer;
-    }
     // Set up some parameters, per juberti. Set MTU.
     if(mPtrViENetwork->SetMTU(mChannel, 1200) != 0)
     {
       CSFLogError(logTag,  "%s MTU Failed %d ", __FUNCTION__,
                   mPtrViEBase->LastError());
       return kMediaConduitMTUError;
     }
     // Turn on RTCP and loss feedback reporting.
     if(mPtrRTP->SetRTCPStatus(mChannel, webrtc::kRtcpCompound_RFC4585) != 0)
     {
       CSFLogError(logTag,  "%s RTCPStatus Failed %d ", __FUNCTION__,
                   mPtrViEBase->LastError());
       return kMediaConduitRTCPStatusError;
     }
   }
 
+  if (receiving) {
+    if (mPtrViERender->AddRenderer(mChannel,
+                                  webrtc::kVideoI420,
+                                  (webrtc::ExternalRenderer*) this) == -1) {
+        CSFLogError(logTag, "%s Failed to added external renderer ", __FUNCTION__);
+        return kMediaConduitInvalidRenderer;
+    }
+  }
+
   CSFLogError(logTag, "%s Initialization Done", __FUNCTION__);
   return kMediaConduitNoError;
 }
 
 void
 WebrtcVideoConduit::SyncTo(WebrtcAudioConduit *aConduit)
 {
   CSFLogDebug(logTag, "%s Synced to %p", __FUNCTION__, aConduit);
@@ -1233,16 +1238,17 @@ WebrtcVideoConduit::FrameSizeChange(unsi
   CSFLogError(logTag,  "%s Renderer is NULL ", __FUNCTION__);
   return -1;
 }
 
 int
 WebrtcVideoConduit::DeliverFrame(unsigned char* buffer,
                                  int buffer_size,
                                  uint32_t time_stamp,
+                                 int64_t ntp_time_ms,
                                  int64_t render_time,
                                  void *handle)
 {
   CSFLogDebug(logTag,  "%s Buffer Size %d", __FUNCTION__, buffer_size);
 
   if(mRenderer)
   {
     layers::Image* img = nullptr;
@@ -1313,17 +1319,18 @@ WebrtcVideoConduit::CodecConfigToWebRTCC
   cinst.startBitrate = mStartBitrate;
   cinst.maxBitrate = mMaxBitrate;
 
   if (cinst.codecType == webrtc::kVideoCodecH264)
   {
 #ifdef MOZ_WEBRTC_OMX
     cinst.resolution_divisor = 16;
 #endif
-    cinst.codecSpecific.H264.profile = codecInfo->mProfile;
+    // cinst.codecSpecific.H264.profile = ?
+    cinst.codecSpecific.H264.profile_byte = codecInfo->mProfile;
     cinst.codecSpecific.H264.constraints = codecInfo->mConstraints;
     cinst.codecSpecific.H264.level = codecInfo->mLevel;
     cinst.codecSpecific.H264.packetizationMode = codecInfo->mPacketizationMode;
     if (codecInfo->mMaxBitrate > 0 && codecInfo->mMaxBitrate < cinst.maxBitrate) {
       cinst.maxBitrate = codecInfo->mMaxBitrate;
     }
     if (codecInfo->mMaxMBPS > 0) {
       // Not supported yet!
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -177,18 +177,18 @@ public:
 
 
   /**
    * Webrtc External Renderer Implementation APIs.
    * Raw I420 Frames are delivred to the VideoConduit by the VideoEngine
    */
   virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int) MOZ_OVERRIDE;
 
-  virtual int DeliverFrame(unsigned char*,int, uint32_t , int64_t,
-                           void *handle) MOZ_OVERRIDE;
+  virtual int DeliverFrame(unsigned char*, int, uint32_t , int64_t,
+                           int64_t, void *handle) MOZ_OVERRIDE;
 
   /**
    * Does DeliverFrame() support a null buffer and non-null handle
    * (video texture)?
    * B2G support it (when using HW video decoder with graphic buffer output).
    * XXX Investigate!  Especially for Android
    */
   virtual bool IsTextureSupported() MOZ_OVERRIDE {
@@ -221,17 +221,18 @@ public:
       return mCurSendCodecConfig->mMaxFrameRate;
     }
     return 0;
   }
 
   WebrtcVideoConduit();
   virtual ~WebrtcVideoConduit();
 
-  MediaConduitErrorCode Init(WebrtcVideoConduit *other);
+  MediaConduitErrorCode Init(WebrtcVideoConduit *other,
+                             bool receiving);
 
   int GetChannel() { return mChannel; }
   webrtc::VideoEngine* GetVideoEngine() { return mVideoEngine; }
   bool GetLocalSSRC(unsigned int* ssrc) MOZ_OVERRIDE;
   bool SetLocalSSRC(unsigned int ssrc) MOZ_OVERRIDE;
   bool GetRemoteSSRC(unsigned int* ssrc) MOZ_OVERRIDE;
   bool SetLocalCNAME(const char* cname) MOZ_OVERRIDE;
   bool GetVideoEncoderStats(double* framerateMean,
--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -441,16 +441,21 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoE
         // Really that it's not in the enum
         LOG(PR_LOG_ERROR,
             ("GMP plugin returned incorrect type (%d)", aEncodedFrame->BufferType()));
         // XXX Bug 1041232 - need a better API for interfacing to the
         // plugin so we can kill it here
         return;
     }
 
+    struct nal_entry {
+      uint32_t offset;
+      uint32_t size;
+    };
+    nsTArray<nal_entry> nals;
     uint32_t size;
     // make sure we don't read past the end of the buffer getting the size
     while (buffer+size_bytes < end) {
       switch (aEncodedFrame->BufferType()) {
         case GMP_BufferSingle:
           size = aEncodedFrame->Size();
           break;
         case GMP_BufferLength8:
@@ -479,30 +484,44 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoE
       }
       if (buffer+size > end) {
         // XXX see above - should we kill the plugin for returning extra bytes?  Probably
         LOG(PR_LOG_ERROR,
             ("GMP plugin returned badly formatted encoded data: end is %td bytes past buffer end",
              buffer+size - end));
         return;
       }
-      webrtc::EncodedImage unit(buffer, size, size);
-      unit._frameType = ft;
-      unit._timeStamp = timestamp;
-      unit._completeFrame = true;
-
-      mCallback->Encoded(unit, nullptr, nullptr);
-
+      // XXX optimize by making buffer an offset
+      nal_entry nal = {((uint32_t) (buffer-aEncodedFrame->Buffer())), (uint32_t) size};
+      nals.AppendElement(nal);
       buffer += size;
       // on last one, buffer == end normally
     }
     if (buffer != end) {
       // At most 3 bytes can be left over, depending on buffertype
       LOGD(("GMP plugin returned %td extra bytes", end - buffer));
     }
+
+    size_t num_nals = nals.Length();
+    if (num_nals > 0) {
+      webrtc::RTPFragmentationHeader fragmentation;
+      fragmentation.VerifyAndAllocateFragmentationHeader(num_nals);
+      for (size_t i = 0; i < num_nals; i++) {
+        fragmentation.fragmentationOffset[i] = nals[i].offset;
+        fragmentation.fragmentationLength[i] = nals[i].size;
+      }
+
+      webrtc::EncodedImage unit(aEncodedFrame->Buffer(), size, size);
+      unit._frameType = ft;
+      unit._timeStamp = timestamp;
+      unit._completeFrame = true;
+
+      mCallback->Encoded(unit, nullptr, &fragmentation);
+
+    }
   }
 }
 
 // Decoder.
 WebrtcGmpVideoDecoder::WebrtcGmpVideoDecoder() :
   mGMP(nullptr),
   mHost(nullptr),
   mCallback(nullptr),
--- a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
@@ -16,18 +16,18 @@
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <OMX_Component.h>
 using namespace android;
 
 // WebRTC
-#include "common_video/interface/texture_video_frame.h"
-#include "video_engine/include/vie_external_codec.h"
+#include "webrtc/common_video/interface/texture_video_frame.h"
+#include "webrtc/video_engine/include/vie_external_codec.h"
 #include "runnable_utils.h"
 
 // Gecko
 #include "GonkNativeWindow.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Mutex.h"
 #include "nsThreadUtils.h"
 #include "OMXCodecWrapper.h"
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
 // Original author: ekr@rtfm.com
 
-#include "logging.h"
 #include "MediaPipeline.h"
 
 #ifndef USE_FAKE_MEDIA_STREAMS
 #include "MediaStreamGraphImpl.h"
 #endif
 
 #include <math.h>
 
@@ -40,18 +39,17 @@
 #include "runnable_utils.h"
 #include "libyuv/convert.h"
 #ifdef MOZILLA_INTERNAL_API
 #include "mozilla/PeerIdentity.h"
 #endif
 #include "mozilla/gfx/Point.h"
 #include "mozilla/gfx/Types.h"
 
-#include "webrtc/modules/interface/module_common_types.h"
-#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "logging.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // Logging context
 MOZ_MTLOG_MODULE("mediapipeline")
 
 namespace mozilla {
--- a/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
+++ b/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
@@ -603,17 +603,17 @@ MediaPipelineFactory::CreateVideoConduit
   // Instantiate an appropriate conduit
   RefPtr<MediaSessionConduit> peerConduit =
       mPCMedia->GetConduit(aTrackPair.mLevel, !receiving);
   MOZ_ASSERT_IF(peerConduit, peerConduit->type() == MediaSessionConduit::VIDEO);
 
   // The two sides of a send/receive pair of conduits each keep a raw
   // pointer to the other, and are responsible for cleanly shutting down.
   RefPtr<VideoSessionConduit> conduit = VideoSessionConduit::Create(
-      static_cast<VideoSessionConduit*>(peerConduit.get()));
+      static_cast<VideoSessionConduit*>(peerConduit.get()), receiving);
 
   if (!conduit) {
     MOZ_MTLOG(ML_ERROR, "Could not create video conduit");
     return NS_ERROR_FAILURE;
   }
 
   mPCMedia->AddConduit(aTrackPair.mLevel, receiving, conduit);
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -313,19 +313,16 @@ nsresult PeerConnectionMedia::UpdateMedi
 
   for (size_t i = 0; i < numPairs; ++i) {
     nsresult rv = session.GetNegotiatedTrackPair(i, &pair);
     if (NS_FAILED(rv)) {
       MOZ_ASSERT(false);
       return rv;
     }
 
-    // TODO(bug 1099318): We are forced to do receive then transmit, because of
-    // a bug in the VideoConduit code. This will need to be fixed for
-    // renegotiation.
     if (pair->mReceiving) {
       rv = factory.CreateMediaPipeline(*pair, *pair->mReceiving);
       if (NS_FAILED(rv)) {
         CSFLogError(logTag, "Failed to create receiving pipeline, rv=%u",
                             static_cast<unsigned>(rv));
         return rv;
       }
     }
--- a/media/webrtc/signaling/test/mediaconduit_unittests.cpp
+++ b/media/webrtc/signaling/test/mediaconduit_unittests.cpp
@@ -590,25 +590,27 @@ class TransportConduitTest : public ::te
   void TestDummyVideoAndTransport(bool send_vp8 = true, const char *source_file = nullptr)
   {
     int err = 0;
     //get pointer to VideoSessionConduit
     mozilla::SyncRunnable::DispatchToThread(gMainThread,
                                             WrapRunnableNMRet(
                                                 &mozilla::VideoSessionConduit::Create,
                                                 nullptr,
+                                                false,
                                                 &mVideoSession));
     if( !mVideoSession )
       ASSERT_NE(mVideoSession, (void*)nullptr);
 
    // This session is for other one
     mozilla::SyncRunnable::DispatchToThread(gMainThread,
                                             WrapRunnableNMRet(
                                                 &mozilla::VideoSessionConduit::Create,
                                                 nullptr,
+                                                true,
                                                 &mVideoSession2));
     if( !mVideoSession2 )
       ASSERT_NE(mVideoSession2,(void*)nullptr);
 
     if (!send_vp8) {
       SetGmpCodecs();
     }
 
@@ -690,16 +692,17 @@ class TransportConduitTest : public ::te
   {
     int err = 0;
     mozilla::RefPtr<mozilla::VideoSessionConduit> videoSession;
     //get pointer to VideoSessionConduit
     mozilla::SyncRunnable::DispatchToThread(gMainThread,
                                             WrapRunnableNMRet(
                                                 &mozilla::VideoSessionConduit::Create,
                                                 nullptr,
+                                                true,
                                                 &videoSession));
     if( !videoSession )
       ASSERT_NE(videoSession, (void*)nullptr);
 
     //Test Configure Recv Codec APIS
     cerr << "   *************************************************" << endl;
     cerr << "    Test Receive Codec Configuration API Now " << endl;
     cerr << "   *************************************************" << endl;
@@ -802,16 +805,17 @@ class TransportConduitTest : public ::te
   {
     int err = 0;
 
     // Get pointer to VideoSessionConduit.
     mozilla::SyncRunnable::DispatchToThread(gMainThread,
                                             WrapRunnableNMRet(
                                                 &mozilla::VideoSessionConduit::Create,
                                                 nullptr,
+                                                false,
                                                 &mVideoSession));
     if( !mVideoSession )
       ASSERT_NE(mVideoSession, (void*)nullptr);
 
     // Configure send codecs on the conduit.
     mozilla::VideoCodecConfig cinst1(120, "VP8", max_fs);
 
     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
deleted file mode 100644
--- a/media/webrtc/trunk/base/base.Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-export builddir_name ?= trunk/base/out
-.PHONY: all
-all:
-	$(MAKE) -C .. base
deleted file mode 100644
--- a/media/webrtc/trunk/base/base.gyp
+++ /dev/null
@@ -1,25 +0,0 @@
-# Below are normally provided by Chromium's base.gyp and required for
-# libjingle.gyp.
-{
-  'targets': [
-    {
-      'target_name': 'base',
-      'type': 'none',
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '..',
-        ],
-      },
-      'conditions': [
-        ['OS == "linux"', {
-          'link_settings': {
-            'libraries': [
-              # We need rt for clock_gettime() used in libjingle.
-              '-lrt',
-            ],
-          },
-        }],
-      ],
-    },
-  ],
-}
deleted file mode 100644
--- a/media/webrtc/trunk/base/base.target.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := base
-### Rules for final target.
-$(obj).target/base/base.stamp: TOOLSET := $(TOOLSET)
-$(obj).target/base/base.stamp:  FORCE_DO_CMD
-	$(call do_cmd,touch)
-
-all_deps += $(obj).target/base/base.stamp
-# Add target alias
-.PHONY: base
-base: $(obj).target/base/base.stamp
-
-# Add target alias to "all" target.
-.PHONY: all
-all: base
-
--- a/media/webrtc/trunk/peerconnection.gyp
+++ b/media/webrtc/trunk/peerconnection.gyp
@@ -30,18 +30,20 @@
 	  'inputs': [
 	     'dummy_file.txt',
           ],
           'message': 'Generating scream',
         }, ],
         'dependencies': [
           'webrtc/modules/modules.gyp:audio_device',
           'webrtc/modules/modules.gyp:video_capture_module',
-#          'webrtc/modules/modules.gyp:video_render_module',
+	  'webrtc/modules/modules.gyp:video_capture_module_internal_impl',
+          'webrtc/modules/modules.gyp:video_render_module_impl',
 #          'webrtc/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+#	  'webrtc/system_wrappers/source/system_wrappers.gyp:metrics_default',
           'webrtc/video_engine/video_engine.gyp:video_engine_core',
           'webrtc/voice_engine/voice_engine.gyp:voice_engine',
         ],
         'conditions': [
           ['OS!="android"', {
             'dependencies': [
               'webrtc/modules/modules.gyp:desktop_capture',
             ],
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/BUILD.gn
@@ -0,0 +1,245 @@
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+# TODO(kjellander): Rebase this to webrtc/build/common.gypi changes after r6330.
+
+import("//build/config/arm.gni")
+import("//build/config/crypto.gni")
+import("//build/config/linux/pkg_config.gni")
+import("build/webrtc.gni")
+
+# Contains the defines and includes in common.gypi that are duplicated both as
+# target_defaults and direct_dependent_settings.
+config("common_inherited_config") {
+  defines = []
+  if (build_with_mozilla) {
+    defines += [ "WEBRTC_MOZILLA_BUILD" ]
+  }
+  if (build_with_chromium) {
+    defines = [
+      "WEBRTC_CHROMIUM_BUILD",
+    ]
+    include_dirs = [
+      # overrides must be included first as that is the mechanism for
+      # selecting the override headers in Chromium.
+      "overrides",
+      # Allow includes to be prefixed with webrtc/ in case it is not an
+      # immediate subdirectory of the top-level.
+      "..",
+    ]
+  }
+  if (is_posix) {
+    defines += [ "WEBRTC_POSIX" ]
+  }
+  if (is_ios) {
+    defines += [
+      "WEBRTC_MAC",
+      "WEBRTC_IOS",
+    ]
+  }
+  if (is_linux) {
+    defines += [ "WEBRTC_LINUX" ]
+  }
+  if (is_mac) {
+    defines += [ "WEBRTC_MAC" ]
+  }
+  if (is_win) {
+    defines += [ "WEBRTC_WIN" ]
+  }
+  if (is_android) {
+    defines += [
+      "WEBRTC_LINUX",
+      "WEBRTC_ANDROID",
+    ]
+    if (rtc_enable_android_opensl) {
+      defines += [ "WEBRTC_ANDROID_OPENSLES" ]
+    }
+  }
+}
+
+if (rtc_have_dbus_glib) {
+  pkg_config("dbus-glib") {
+    packages = [ "dbus-glib-1" ]
+  }
+}
+
+config("common_config") {
+  cflags = []
+  cflags_cc = []
+  if (rtc_restrict_logging) {
+    defines = [ "WEBRTC_RESTRICT_LOGGING" ]
+  }
+
+  if (rtc_have_dbus_glib) {
+    defines += [ "HAVE_DBUS_GLIB" ]
+    # TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
+    # is still not found even if the execution of
+    # build/config/linux/pkg-config.py dbus-glib-1 returns correct include
+    # dirs on Linux.
+    all_dependent_configs = [ "dbus-glib" ]
+  }
+
+  if (rtc_enable_video) {
+    defines += [ "WEBRTC_MODULE_UTILITY_VIDEO" ]
+  }
+
+  if (build_with_chromium) {
+    defines += [ "LOGGING_INSIDE_WEBRTC" ]
+  } else {
+    if (is_posix) {
+      # -Wextra is currently disabled in Chromium"s common.gypi. Enable
+      # for targets that can handle it. For Android/arm64 right now
+      # there will be an "enumeral and non-enumeral type in conditional
+      # expression" warning in android_tools/ndk_experimental"s version
+      # of stlport.
+      # See: https://code.google.com/p/chromium/issues/detail?id=379699
+      if (cpu_arch != "arm64" || !is_android) {
+        cflags = [
+          "-Wextra",
+          # We need to repeat some flags from Chromium"s common.gypi
+          # here that get overridden by -Wextra.
+          "-Wno-unused-parameter",
+          "-Wno-missing-field-initializers",
+          "-Wno-strict-overflow",
+        ]
+        cflags_cc = [
+          "-Wnon-virtual-dtor",
+          # This is enabled for clang; enable for gcc as well.
+          "-Woverloaded-virtual",
+        ]
+      }
+    }
+
+    if (is_clang) {
+      cflags += [ "-Wthread-safety" ]
+    }
+  }
+
+  if (cpu_arch == "arm64") {
+    defines += [ "WEBRTC_ARCH_ARM" ]
+  }
+
+  if (cpu_arch == "arm") {
+    defines += [ "WEBRTC_ARCH_ARM" ]
+    if (arm_version == 7) {
+      defines += [ "WEBRTC_ARCH_ARM_V7" ]
+      if (arm_use_neon) {
+        defines += [ "WEBRTC_ARCH_ARM_NEON" ]
+      } else {
+        defines += [ "WEBRTC_DETECT_ARM_NEON" ]
+      }
+    }
+  }
+
+  if (cpu_arch == "mipsel") {
+    defines += [ "MIPS32_LE" ]
+    if (mips_fpu) {
+      defines += [ "MIPS_FPU_LE" ]
+      cflags += [ "-mhard-float" ]
+    } else {
+      cflags += [ "-msoft-float" ]
+    }
+    if (mips_arch_variant == "mips32r2") {
+      defines += [ "MIPS32_R2_LE" ]
+      cflags += [ "-mips32r2" ]
+      cflags_cc += [ "-mips32r2" ]
+    }
+    if (mips_dsp_rev == 1) {
+      defines += [ "MIPS_DSP_R1_LE" ]
+      cflags += [ "-mdsp" ]
+      cflags_cc += [ "-mdsp" ]
+    } else if (mips_dsp_rev == 2) {
+      defines += [
+        "MIPS_DSP_R1_LE",
+        "MIPS_DSP_R2_LE",
+      ]
+      cflags += [ "-mdspr2" ]
+      cflags_cc += [ "-mdspr2" ]
+    }
+  }
+
+  # TODO(kjellander): Handle warnings on Windows where WebRTC differ from the
+  # default warnings set in build/config/compiler/BUILD.gn.
+
+  if (is_android && is_clang) {
+    # The Android NDK doesn"t provide optimized versions of these
+    # functions. Ensure they are disabled for all compilers.
+    cflags += [
+      "-fno-builtin-cos",
+      "-fno-builtin-sin",
+      "-fno-builtin-cosf",
+      "-fno-builtin-sinf",
+    ]
+  }
+}
+
+static_library("webrtc") {
+  sources = [
+    "call.h",
+    "config.h",
+    "experiments.h",
+    "frame_callback.h",
+    "transport.h",
+  ]
+
+  configs += [ ":common_config" ]
+  public_configs = [ ":common_inherited_config"]
+
+  deps = [
+    ":webrtc_common",
+    "base:webrtc_base",
+    "common_audio",
+    "common_video",
+    "modules/audio_coding",
+    "modules/audio_conference_mixer",
+    "modules/audio_device",
+    "modules/audio_processing",
+    "modules/bitrate_controller",
+    "modules/desktop_capture",
+    "modules/media_file",
+    "modules/rtp_rtcp",
+    "modules/utility",
+    "modules/video_capture",
+    "modules/video_coding",
+    "modules/video_processing",
+    "modules/video_render",
+    "system_wrappers",
+    "tools",
+    "video",
+    "video_engine",
+    "voice_engine",
+  ]
+}
+
+if (!build_with_chromium) {
+  executable("webrtc_tests") {
+    testonly = true
+    deps = [
+      ":webrtc",
+      "modules/video_render:video_render_internal_impl",
+      "modules/video_capture:video_capture_internal_impl",
+      "test",
+    ]
+  }
+}
+
+source_set("webrtc_common") {
+  sources = [
+    "config.h",
+    "config.cc",
+  ]
+
+  if (is_clang) {
+    # Suppress warnings from Chrome's Clang plugins.
+    # See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
+    configs -= [ "//build/config/clang:find_bad_constructs" ]
+  }
+
+  configs += [ ":common_config" ]
+  public_configs = [ ":common_inherited_config" ]
+}
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/OWNERS
@@ -0,0 +1,8 @@
+per-file *.isolate=kjellander@webrtc.org
+
+# These are for the common case of adding or renaming files. If you're doing
+# structural changes, please get a review from a reviewer in this file.
+per-file *.gyp=*
+per-file *.gypi=*
+
+per-file BUILD.gn=kjellander@webrtc.org
--- a/media/webrtc/trunk/webrtc/PRESUBMIT.py
+++ b/media/webrtc/trunk/webrtc/PRESUBMIT.py
@@ -3,23 +3,23 @@
 # Use of this source code is governed by a BSD-style license
 # that can be found in the LICENSE file in the root of the source
 # tree. An additional intellectual property rights grant can be found
 # in the file PATENTS.  All contributing project authors may
 # be found in the AUTHORS file in the root of the source tree.
 
 def _LicenseHeader(input_api):
   """Returns the license header regexp."""
-  # Accept any year number from 2011 to the current year
+  # Accept any year number from 2003 to the current year
   current_year = int(input_api.time.strftime('%Y'))
-  allowed_years = (str(s) for s in reversed(xrange(2011, current_year + 1)))
+  allowed_years = (str(s) for s in reversed(xrange(2003, current_year + 1)))
   years_re = '(' + '|'.join(allowed_years) + ')'
   license_header = (
-      r'.*? Copyright \(c\) %(year)s The WebRTC project authors\. '
-        r'All Rights Reserved\.\n'
+      r'.*? Copyright( \(c\))? %(year)s The WebRTC [Pp]roject [Aa]uthors\. '
+        r'All [Rr]ights [Rr]eserved\.\n'
       r'.*?\n'
       r'.*? Use of this source code is governed by a BSD-style license\n'
       r'.*? that can be found in the LICENSE file in the root of the source\n'
       r'.*? tree\. An additional intellectual property rights grant can be '
         r'found\n'
       r'.*? in the file PATENTS\.  All contributing project authors may\n'
       r'.*? be found in the AUTHORS file in the root of the source tree\.\n'
   ) % {
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/BUILD.gn
@@ -0,0 +1,600 @@
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("//build/config/crypto.gni")
+import("//build/config/ui.gni")
+import("../build/webrtc.gni")
+
+config("webrtc_base_config") {
+  include_dirs = [
+    "//third_party/jsoncpp/overrides/include",
+    "//third_party/jsoncpp/source/include",
+  ]
+
+  defines = [
+    "FEATURE_ENABLE_SSL",
+    "LOGGING=1",
+    "USE_WEBRTC_DEV_BRANCH",
+  ]
+
+  # TODO(henrike): issue 3307, make webrtc_base build without disabling
+  # these flags.
+  cflags_cc = [ "-Wno-non-virtual-dtor" ]
+}
+
+config("webrtc_base_chromium_config") {
+  defines = [
+    "NO_MAIN_THREAD_WRAPPING",
+  ]
+}
+
+config("openssl_config") {
+  defines = [
+    "SSL_USE_OPENSSL",
+    "HAVE_OPENSSL_SSL_H",
+  ]
+}
+
+config("nss_config") {
+  defines = [
+    "SSL_USE_NSS",
+    "HAVE_NSS_SSL_H",
+    "SSL_USE_NSS_RNG",
+  ]
+}
+
+config("ios_config") {
+  ldflags = [
+    #"Foundation.framework",  # Already included in //build/config:default_libs.
+    "Security.framework",
+    "SystemConfiguration.framework",
+    #"UIKit.framework",  # Already included in //build/config:default_libs.
+  ]
+}
+
+config("mac_config") {
+  ldflags = [
+    "Cocoa.framework",
+    #"Foundation.framework",  # Already included in //build/config:default_libs.
+    #"IOKit.framework",  # Already included in //build/config:default_libs.
+    #"Security.framework",  # Already included in //build/config:default_libs.
+    "SystemConfiguration.framework",
+  ]
+}
+
+config("mac_x86_config") {
+  libs = [
+    #"Carbon.framework",  # Already included in //build/config:default_libs.
+  ]
+}
+
+if (is_linux && !build_with_chromium) {
+  # Provides the same functionality as the //crypto:platform target, which
+  # WebRTC cannot use as we don't sync src/crypto from Chromium.
+  group("linux_system_ssl") {
+    if (use_openssl) {
+      deps = [ "//third_party/boringssl" ]
+    } else {
+      deps = [ "//net/third_party/nss/ssl:libssl" ]
+
+      public_configs = [
+        "//net/third_party/nss/ssl:ssl_config",
+        "//third_party/nss:system_nss_no_ssl_config",
+      ]
+    }
+  }
+}
+
+if (rtc_build_ssl == 0) {
+  config("external_ssl_library") {
+    assert(rtc_ssl_root != "",
+           "You must specify rtc_ssl_root when rtc_build_ssl==0.")
+    include_dirs = [ rtc_ssl_root ]
+  }
+}
+
+# The subset of rtc_base approved for use outside of libjingle.
+static_library("rtc_base_approved") {
+  configs += [ "..:common_config" ]
+  public_configs = [ "..:common_inherited_config" ]
+
+  sources = [
+    "checks.cc",
+    "checks.h",
+    "exp_filter.cc",
+    "exp_filter.h",
+    "md5.cc",
+    "md5.h",
+    "md5digest.h",
+    "platform_file.cc",
+    "platform_file.h",
+    "stringencode.cc",
+    "stringencode.h",
+    "stringutils.cc",
+    "stringutils.h",
+    "thread_annotations.h",
+    "timeutils.cc",
+    "timeutils.h",
+  ]
+}
+
+static_library("webrtc_base") {
+  cflags = []
+  cflags_cc = []
+  libs = []
+  deps = [
+    ":rtc_base_approved",
+  ]
+
+  configs += [
+    "..:common_config",
+    ":webrtc_base_config",
+  ]
+
+  public_configs = [
+    "..:common_inherited_config",
+    ":webrtc_base_config",
+  ]
+
+  defines = [
+    "LOGGING=1",
+    "USE_WEBRTC_DEV_BRANCH",
+  ]
+
+  sources = [
+    "asyncfile.cc",
+    "asyncfile.h",
+    "asynchttprequest.cc",
+    "asynchttprequest.h",
+    "asyncpacketsocket.h",
+    "asyncsocket.cc",
+    "asyncsocket.h",
+    "asynctcpsocket.cc",
+    "asynctcpsocket.h",
+    "asyncudpsocket.cc",
+    "asyncudpsocket.h",
+    "autodetectproxy.cc",
+    "autodetectproxy.h",
+    "base64.cc",
+    "base64.h",
+    "basicdefs.h",
+    "bytebuffer.cc",
+    "bytebuffer.h",
+    "byteorder.h",
+    "common.cc",
+    "common.h",
+    "cpumonitor.cc",
+    "cpumonitor.h",
+    "crc32.cc",
+    "crc32.h",
+    "criticalsection.h",
+    "cryptstring.h",
+    "diskcache.cc",
+    "diskcache.h",
+    "event.cc",
+    "event.h",
+    "fileutils.cc",
+    "fileutils.h",
+    "firewallsocketserver.cc",
+    "firewallsocketserver.h",
+    "flags.cc",
+    "flags.h",
+    "gunit_prod.h",
+    "helpers.cc",
+    "helpers.h",
+    "httpbase.cc",
+    "httpbase.h",
+    "httpclient.cc",
+    "httpclient.h",
+    "httpcommon-inl.h",
+    "httpcommon.cc",
+    "httpcommon.h",
+    "httprequest.cc",
+    "httprequest.h",
+    "iosfilesystem.mm",
+    "ipaddress.cc",
+    "ipaddress.h",
+    "linked_ptr.h",
+    "mathutils.h",
+    "messagedigest.cc",
+    "messagedigest.h",
+    "messagehandler.cc",
+    "messagehandler.h",
+    "messagequeue.cc",
+    "messagequeue.h",
+    "nethelpers.cc",
+    "nethelpers.h",
+    "network.cc",
+    "network.h",
+    "nullsocketserver.h",
+    "pathutils.cc",
+    "pathutils.h",
+    "physicalsocketserver.cc",
+    "physicalsocketserver.h",
+    "proxydetect.cc",
+    "proxydetect.h",
+    "proxyinfo.cc",
+    "proxyinfo.h",
+    "ratelimiter.cc",
+    "ratelimiter.h",
+    "ratetracker.cc",
+    "ratetracker.h",
+    "safe_conversions.h",
+    "safe_conversions_impl.h",
+    "scoped_autorelease_pool.h",
+    "scoped_autorelease_pool.mm",
+    "scoped_ptr.h",
+    "sha1.cc",
+    "sha1.h",
+    "sha1digest.h",
+    "signalthread.cc",
+    "signalthread.h",
+    "sigslot.h",
+    "sigslotrepeater.h",
+    "socket.h",
+    "socketadapters.cc",
+    "socketadapters.h",
+    "socketaddress.cc",
+    "socketaddress.h",
+    "socketaddresspair.cc",
+    "socketaddresspair.h",
+    "socketfactory.h",
+    "socketpool.cc",
+    "socketpool.h",
+    "socketserver.h",
+    "socketstream.cc",
+    "socketstream.h",
+    "ssladapter.cc",
+    "ssladapter.h",
+    "sslfingerprint.cc",
+    "sslfingerprint.h",
+    "sslidentity.cc",
+    "sslidentity.h",
+    "sslsocketfactory.cc",
+    "sslsocketfactory.h",
+    "sslstreamadapter.cc",
+    "sslstreamadapter.h",
+    "sslstreamadapterhelper.cc",
+    "sslstreamadapterhelper.h",
+    "stream.cc",
+    "stream.h",
+    "systeminfo.cc",
+    "systeminfo.h",
+    "task.cc",
+    "task.h",
+    "taskparent.cc",
+    "taskparent.h",
+    "taskrunner.cc",
+    "taskrunner.h",
+    "thread.cc",
+    "thread.h",
+    "thread_checker.h",
+    "thread_checker_impl.cc",
+    "thread_checker_impl.h",
+    "timing.cc",
+    "timing.h",
+    "urlencode.cc",
+    "urlencode.h",
+    "worker.cc",
+    "worker.h",
+  ]
+
+  if (is_posix) {
+    sources += [
+      "unixfilesystem.cc",
+      "unixfilesystem.h",
+    ]
+  }
+
+  if (build_with_chromium) {
+    sources += [
+      "../overrides/webrtc/base/basictypes.h",
+      "../overrides/webrtc/base/constructormagic.h",
+      "../overrides/webrtc/base/logging.cc",
+      "../overrides/webrtc/base/logging.h",
+    ]
+
+    if (is_win) {
+      sources += [ "../overrides/webrtc/base/win32socketinit.cc" ]
+    }
+
+    include_dirs = [
+      "../overrides",
+      "../../boringssl/src/include",
+    ]
+
+    public_configs += [ ":webrtc_base_chromium_config" ]
+  } else {
+    sources += [
+      "asyncinvoker.cc",
+      "asyncinvoker.h",
+      "asyncinvoker-inl.h",
+      "asyncresolverinterface.h",
+      "atomicops.h",
+      "bandwidthsmoother.cc",
+      "bandwidthsmoother.h",
+      "basictypes.h",
+      "bind.h",
+      "bind.h.pump",
+      "buffer.h",
+      "callback.h",
+      "callback.h.pump",
+      "constructormagic.h",
+      "filelock.cc",
+      "filelock.h",
+      "fileutils_mock.h",
+      "genericslot.h",
+      "genericslot.h.pump",
+      "httpserver.cc",
+      "httpserver.h",
+      "json.cc",
+      "json.h",
+      "logging.cc",
+      "logging.h",
+      "mathutils.h",
+      "multipart.cc",
+      "multipart.h",
+      "natserver.cc",
+      "natserver.h",
+      "natsocketfactory.cc",
+      "natsocketfactory.h",
+      "nattypes.cc",
+      "nattypes.h",
+      "optionsfile.cc",
+      "optionsfile.h",
+      "profiler.cc",
+      "profiler.h",
+      "proxyserver.cc",
+      "proxyserver.h",
+      "refcount.h",
+      "referencecountedsingletonfactory.h",
+      "rollingaccumulator.h",
+      "scopedptrcollection.h",
+      "scoped_ref_ptr.h",
+      "sec_buffer.h",
+      "sharedexclusivelock.cc",
+      "sharedexclusivelock.h",
+      "sslconfig.h",
+      "sslroots.h",
+      "stringdigest.h",
+      "testclient.cc",
+      "testclient.h",
+      "transformadapter.cc",
+      "transformadapter.h",
+      "versionparsing.cc",
+      "versionparsing.h",
+      "virtualsocketserver.cc",
+      "virtualsocketserver.h",
+      "window.h",
+      "windowpickerfactory.h",
+      "windowpicker.h",
+    ]
+
+    if (is_posix) {
+      sources += [
+        "latebindingsymboltable.cc",
+        "latebindingsymboltable.cc.def",
+        "latebindingsymboltable.h",
+        "latebindingsymboltable.h.def",
+        "posix.cc",
+        "posix.h",
+      ]
+    }
+
+    if (is_linux) {
+      sources += [
+        "dbus.cc",
+        "dbus.h",
+        "libdbusglibsymboltable.cc",
+        "libdbusglibsymboltable.h",
+        "linuxfdwalk.c",
+        "linuxfdwalk.h",
+      ]
+    }
+
+    if (is_mac) {
+      sources += [
+        "macasyncsocket.cc",
+        "macasyncsocket.h",
+        "maccocoasocketserver.h",
+        "maccocoasocketserver.mm",
+        "macsocketserver.cc",
+        "macsocketserver.h",
+        "macwindowpicker.cc",
+        "macwindowpicker.h",
+      ]
+    }
+
+    if (is_win) {
+      sources += [
+        "diskcache_win32.cc",
+        "diskcache_win32.h",
+        "win32regkey.cc",
+        "win32regkey.h",
+        "win32socketinit.cc",
+        "win32socketinit.h",
+        "win32socketserver.cc",
+        "win32socketserver.h",
+      ]
+    }
+    if (rtc_build_json) {
+      deps += [ "//third_party/jsoncpp" ]
+    } else {
+      include_dirs += [ rtc_jsoncpp_root ]
+
+      # When defined changes the include path for json.h to where it is
+      # expected to be when building json outside of the standalone build.
+      defines += [ "WEBRTC_EXTERNAL_JSON" ]
+    }
+  }  # !build_with_chromium
+
+  if (is_clang) {
+    # Suppress warnings from the Chrome Clang plugins.
+    # See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
+    configs -= [ "//build/config/clang:find_bad_constructs" ]
+  }
+
+  # TODO(henrike): issue 3307, make webrtc_base build with the Chromium default
+  # compiler settings.
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+  cflags += [ "-Wno-uninitialized" ]
+  cflags_cc += [ "-Wno-non-virtual-dtor" ]
+
+  if (use_openssl) {
+    public_configs += [ ":openssl_config" ]
+    if (rtc_build_ssl) {
+      deps += [ "//third_party/boringssl" ]
+    } else {
+      configs += [ "external_ssl_library" ]
+    }
+    sources += [
+      "openssl.h",
+      "openssladapter.cc",
+      "openssladapter.h",
+      "openssldigest.cc",
+      "openssldigest.h",
+      "opensslidentity.cc",
+      "opensslidentity.h",
+      "opensslstreamadapter.cc",
+      "opensslstreamadapter.h",
+    ]
+  } else {
+    public_configs += [ ":nss_config" ]
+    if (rtc_build_ssl) {
+      if (build_with_chromium) {
+        deps += [ "//crypto:platform" ]
+      } else {
+        deps += [ "//net/third_party/nss/ssl:libssl" ]
+        if (is_linux) {
+          deps += [ ":linux_system_ssl" ]
+        } else {
+          deps += [
+            "//third_party/nss:nspr",
+            "//third_party/nss:nss",
+          ]
+        }
+      }
+    } else {
+      configs += [ "external_ssl_library" ]
+    }
+    sources += [
+      "nssidentity.cc",
+      "nssidentity.h",
+      "nssstreamadapter.cc",
+      "nssstreamadapter.h",
+    ]
+  }
+
+  if (is_android) {
+    sources += [
+      "ifaddrs-android.cc",
+      "ifaddrs-android.h",
+    ]
+
+    libs += [
+      "log",
+      "GLESv2"
+    ]
+  }
+
+  if (is_ios) {
+    all_dependent_configs += [ ":ios_config" ]
+  }
+
+  if (use_x11) {
+    sources += [
+      "x11windowpicker.cc",
+      "x11windowpicker.h",
+    ]
+    libs += [
+      "dl",
+      "rt",
+      "Xext",
+      "X11",
+      "Xcomposite",
+      "Xrender",
+    ]
+  }
+
+  if (is_linux) {
+    libs += [
+      "dl",
+      "rt",
+    ]
+  }
+
+  if (is_mac) {
+    sources += [
+      "maccocoathreadhelper.h",
+      "maccocoathreadhelper.mm",
+      "macconversion.cc",
+      "macconversion.h",
+      "macutils.cc",
+      "macutils.h",
+    ]
+
+    all_dependent_configs = [ ":mac_config" ]
+
+    if (cpu_arch == "x86") {
+      all_dependent_configs += [ ":mac_x86_config" ]
+    }
+  }
+
+  if (is_win) {
+    sources += [
+      "schanneladapter.cc",
+      "schanneladapter.h",
+      "win32.cc",
+      "win32.h",
+      "win32filesystem.cc",
+      "win32filesystem.h",
+      "win32securityerrors.cc",
+      "win32window.cc",
+      "win32window.h",
+      "win32windowpicker.cc",
+      "win32windowpicker.h",
+      "winfirewall.cc",
+      "winfirewall.h",
+      "winping.cc",
+      "winping.h",
+    ]
+
+    libs += [
+      "crypt32.lib",
+      "iphlpapi.lib",
+      "secur32.lib",
+    ]
+
+    cflags += [
+      # Suppress warnings about WIN32_LEAN_AND_MEAN.
+      "/wd4005",
+      "/wd4703",
+    ]
+
+    defines += [ "_CRT_NONSTDC_NO_DEPRECATE" ]
+  }
+
+  if (is_posix && is_debug) {
+    # The Chromium build/common.gypi defines this for all posix
+    # _except_ for ios & mac.  We want it there as well, e.g.
+    # because ASSERT and friends trigger off of it.
+    defines += [ "_DEBUG" ]
+  }
+
+  if (is_ios || (is_mac && cpu_arch != "x86")) {
+    defines += [ "CARBON_DEPRECATED=YES" ]
+  }
+
+  if (is_linux || is_android) {
+    sources += [
+      "linux.cc",
+      "linux.h",
+    ]
+  }
+}
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/OWNERS
@@ -0,0 +1,13 @@
+henrika@webrtc.org
+henrike@webrtc.org
+henrikg@webrtc.org
+hta@webrtc.org
+jiayl@webrtc.org
+juberti@webrtc.org
+mflodman@webrtc.org
+perkj@webrtc.org
+pthatcher@webrtc.org
+sergeyu@chromium.org
+tommi@webrtc.org
+
+per-file BUILD.gn=kjellander@webrtc.org
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/asyncfile.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/base/asyncfile.h"
+
+namespace rtc {
+
+AsyncFile::AsyncFile() {
+}
+
+AsyncFile::~AsyncFile() {
+}
+
+}  // namespace rtc
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/asyncfile.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_BASE_ASYNCFILE_H__
+#define WEBRTC_BASE_ASYNCFILE_H__
+
+#include "webrtc/base/sigslot.h"
+
+namespace rtc {
+
+// Provides the ability to perform file I/O asynchronously.
+// TODO: Create a common base class with AsyncSocket.
+class AsyncFile {
+ public:
+  AsyncFile();
+  virtual ~AsyncFile();
+
+  // Determines whether the file will receive read events.
+  virtual bool readable() = 0;
+  virtual void set_readable(bool value) = 0;
+
+  // Determines whether the file will receive write events.
+  virtual bool writable() = 0;
+  virtual void set_writable(bool value) = 0;
+
+  sigslot::signal1<AsyncFile*> SignalReadEvent;
+  sigslot::signal1<AsyncFile*> SignalWriteEvent;
+  sigslot::signal2<AsyncFile*, int> SignalCloseEvent;
+};
+
+}  // namespace rtc
+
+#endif  // WEBRTC_BASE_ASYNCFILE_H__
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/asynchttprequest.cc
@@ -0,0 +1,116 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/base/asynchttprequest.h"
+
+namespace rtc {
+
+enum {
+  MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
+  MSG_LAUNCH_REQUEST
+};
+static const int kDefaultHTTPTimeout = 30 * 1000;  // 30 sec
+
+///////////////////////////////////////////////////////////////////////////////
+// AsyncHttpRequest
+///////////////////////////////////////////////////////////////////////////////
+
+AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
+    : start_delay_(0),
+      firewall_(NULL),
+      port_(80),
+      secure_(false),
+      timeout_(kDefaultHTTPTimeout),
+      fail_redirect_(false),
+      factory_(Thread::Current()->socketserver(), user_agent),
+      pool_(&factory_),
+      client_(user_agent.c_str(), &pool_),
+      error_(HE_NONE) {
+  client_.SignalHttpClientComplete.connect(this,
+      &AsyncHttpRequest::OnComplete);
+}
+
+AsyncHttpRequest::~AsyncHttpRequest() {
+}
+
+void AsyncHttpRequest::OnWorkStart() {
+  if (start_delay_ <= 0) {
+    LaunchRequest();
+  } else {
+    Thread::Current()->PostDelayed(start_delay_, this, MSG_LAUNCH_REQUEST);
+  }
+}
+
+void AsyncHttpRequest::OnWorkStop() {
+  // worker is already quitting, no need to explicitly quit
+  LOG(LS_INFO) << "HttpRequest cancelled";
+}
+
+void AsyncHttpRequest::OnComplete(HttpClient* client, HttpErrorType error) {
+  Thread::Current()->Clear(this, MSG_TIMEOUT);
+
+  set_error(error);
+  if (!error) {
+    LOG(LS_INFO) << "HttpRequest completed successfully";
+
+    std::string value;
+    if (client_.response().hasHeader(HH_LOCATION, &value)) {
+      response_redirect_ = value.c_str();
+    }
+  } else {
+    LOG(LS_INFO) << "HttpRequest completed with error: " << error;
+  }
+
+  worker()->Quit();
+}
+
+void AsyncHttpRequest::OnMessage(Message* message) {
+  switch (message->message_id) {
+   case MSG_TIMEOUT:
+    LOG(LS_INFO) << "HttpRequest timed out";
+    client_.reset();
+    worker()->Quit();
+    break;
+   case MSG_LAUNCH_REQUEST:
+    LaunchRequest();
+    break;
+   default:
+    SignalThread::OnMessage(message);
+    break;
+  }
+}
+
+void AsyncHttpRequest::DoWork() {
+  // Do nothing while we wait for the request to finish. We only do this so
+  // that we can be a SignalThread; in the future this class should not be
+  // a SignalThread, since it does not need to spawn a new thread.
+  Thread::Current()->ProcessMessages(kForever);
+}
+
+void AsyncHttpRequest::LaunchRequest() {
+  factory_.SetProxy(proxy_);
+  if (secure_)
+    factory_.UseSSL(host_.c_str());
+
+  bool transparent_proxy = (port_ == 80) &&
+           ((proxy_.type == PROXY_HTTPS) || (proxy_.type == PROXY_UNKNOWN));
+  if (transparent_proxy) {
+    client_.set_proxy(proxy_);
+  }
+  client_.set_fail_redirect(fail_redirect_);
+  client_.set_server(SocketAddress(host_, port_));
+
+  LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
+
+  Thread::Current()->PostDelayed(timeout_, this, MSG_TIMEOUT);
+  client_.start();
+}
+
+}  // namespace rtc
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/asynchttprequest.h
@@ -0,0 +1,104 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_BASE_ASYNCHTTPREQUEST_H_
+#define WEBRTC_BASE_ASYNCHTTPREQUEST_H_
+
+#include <string>
+#include "webrtc/base/event.h"
+#include "webrtc/base/httpclient.h"
+#include "webrtc/base/signalthread.h"
+#include "webrtc/base/socketpool.h"
+#include "webrtc/base/sslsocketfactory.h"
+
+namespace rtc {
+
+class FirewallManager;
+
+///////////////////////////////////////////////////////////////////////////////
+// AsyncHttpRequest
+// Performs an HTTP request on a background thread.  Notifies on the foreground
+// thread once the request is done (successfully or unsuccessfully).
+///////////////////////////////////////////////////////////////////////////////
+
+class AsyncHttpRequest : public SignalThread {
+ public:
+  explicit AsyncHttpRequest(const std::string &user_agent);
+  ~AsyncHttpRequest();
+
+  // If start_delay is less than or equal to zero, this starts immediately.
+  // Start_delay defaults to zero.
+  int start_delay() const { return start_delay_; }
+  void set_start_delay(int delay) { start_delay_ = delay; }
+
+  const ProxyInfo& proxy() const { return proxy_; }
+  void set_proxy(const ProxyInfo& proxy) {
+    proxy_ = proxy;
+  }
+  void set_firewall(FirewallManager * firewall) {
+    firewall_ = firewall;
+  }
+
+  // The DNS name of the host to connect to.
+  const std::string& host() { return host_; }
+  void set_host(const std::string& host) { host_ = host; }
+
+  // The port to connect to on the target host.
+  int port() { return port_; }
+  void set_port(int port) { port_ = port; }
+
+  // Whether the request should use SSL.
+  bool secure() { return secure_; }
+  void set_secure(bool secure) { secure_ = secure; }
+
+  // Time to wait on the download, in ms.
+  int timeout() { return timeout_; }
+  void set_timeout(int timeout) { timeout_ = timeout; }
+
+  // Fail redirects to allow analysis of redirect urls, etc.
+  bool fail_redirect() const { return fail_redirect_; }
+  void set_fail_redirect(bool redirect) { fail_redirect_ = redirect; }
+
+  // Returns the redirect when redirection occurs
+  const std::string& response_redirect() { return response_redirect_; }
+
+  HttpRequestData& request() { return client_.request(); }
+  HttpResponseData& response() { return client_.response(); }
+  HttpErrorType error() { return error_; }
+
+ protected:
+  void set_error(HttpErrorType error) { error_ = error; }
+  virtual void OnWorkStart();
+  virtual void OnWorkStop();
+  void OnComplete(HttpClient* client, HttpErrorType error);
+  virtual void OnMessage(Message* message);
+  virtual void DoWork();
+
+ private:
+  void LaunchRequest();
+
+  int start_delay_;
+  ProxyInfo proxy_;
+  FirewallManager* firewall_;
+  std::string host_;
+  int port_;
+  bool secure_;
+  int timeout_;
+  bool fail_redirect_;
+  SslSocketFactory factory_;
+  ReuseSocketPool pool_;
+  HttpClient client_;
+  HttpErrorType error_;
+  std::string response_redirect_;
+};
+
+}  // namespace rtc
+
+#endif  // WEBRTC_BASE_ASYNCHTTPREQUEST_H_
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/base/asynchttprequest_unittest.cc
@@ -0,0 +1,234 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string>
+#include "webrtc/base/asynchttprequest.h"
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/httpserver.h"
+#include "webrtc/base/socketstream.h"
+#include "webrtc/base/thread.h"
+#include "webrtc/test/testsupport/gtest_disable.h"
+
+namespace rtc {
+
+static const SocketAddress kServerAddr("127.0.0.1", 0);
+static const SocketAddress kServerHostnameAddr("localhost", 0);
+static const char kServerGetPath[] = "/get";
+static const char kServerPostPath[] = "/post";
+static const char kServerResponse[] = "This is a test";
+
+class TestHttpServer : public HttpServer, public sigslot::has_slots<> {
+ public:
+  TestHttpServer(Thread* thread, const SocketAddress& addr) :
+      socket_(thread->socketserver()->CreateAsyncSocket(addr.family(),
+                                                        SOCK_STREAM)) {
+    socket_->Bind(addr);
+    socket_->Listen(5);
+    socket_->SignalReadEvent.connect(this, &TestHttpServer::OnAccept);
+  }
+
+  SocketAddress address() const { return socket_->GetLocalAddress(); }
+  void Close() const { socket_->Close(); }
+
+ private:
+  void OnAccept(AsyncSocket* socket) {
+    AsyncSocket* new_socket = socket_->Accept(NULL);
+    if (new_socket) {
+      HandleConnection(new SocketStream(new_socket));
+    }
+  }
+  rtc::scoped_ptr<AsyncSocket> socket_;
+};
+
+class AsyncHttpRequestTest : public testing::Test,
+                             public sigslot::has_slots<> {
+ public:
+  AsyncHttpRequestTest()
+      : started_(false),
+        done_(false),
+        server_(Thread::Current(), kServerAddr) {
+    server_.SignalHttpRequest.connect(this, &AsyncHttpRequestTest::OnRequest);
+  }
+
+  bool started() const { return started_; }
+  bool done() const { return done_; }
+
+  AsyncHttpRequest* CreateGetRequest(const std::string& host, int port,
+                                     const std::string& path) {
+    rtc::AsyncHttpRequest* request =
+        new rtc::AsyncHttpRequest("unittest");
+    request->SignalWorkDone.connect(this,
+        &AsyncHttpRequestTest::OnRequestDone);
+    request->request().verb = rtc::HV_GET;
+    request->set_host(host);
+    request->set_port(port);
+    request->request().path = path;
+    request->response().document.reset(new MemoryStream());
+    return request;
+  }
+  AsyncHttpRequest* CreatePostRequest(const std::string& host, int port,
+                                      const std::string& path,
+                                      const std::string content_type,
+                                      StreamInterface* content) {
<