Merge b2ginbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Mon, 17 Aug 2015 17:05:25 -0700
changeset 258105 90d9b7c391d38ae118865bd87b5d011feee6dded
parent 258104 6ae3e9ff53b2bae8d95a90c9f25368fd81fa357e (current diff)
parent 258100 93a9f980f5ba4df9e287f56d01ddc366e539a095 (diff)
child 258106 ee169a46d67b5b085b9d80ff7f500d243ab02d75
child 258172 eba41ce99321f1c9a2c508164e6991dfc4aedde8
child 258192 fe03a4ac6721d4f462f3cdc46566e330335f3a7e
push id63817
push userkwierso@gmail.com
push dateTue, 18 Aug 2015 00:15:30 +0000
treeherdermozilla-inbound@ee169a46d67b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
first release with
nightly linux32
90d9b7c391d3 / 43.0a1 / 20150818030209 / files
nightly linux64
90d9b7c391d3 / 43.0a1 / 20150818030209 / files
nightly mac
90d9b7c391d3 / 43.0a1 / 20150818030209 / files
nightly win32
90d9b7c391d3 / 43.0a1 / 20150818030209 / files
nightly win64
90d9b7c391d3 / 43.0a1 / 20150818030209 / 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 b2ginbound to central, a=merge
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2d58f4b9206b50b8fda0d5036da6f0c62608db7c"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d70e4bfdcb65e7514de0f9315b74aea1c811678d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="05a36844c1046a1eb07d5b1325f85ed741f961ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2d58f4b9206b50b8fda0d5036da6f0c62608db7c"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d70e4bfdcb65e7514de0f9315b74aea1c811678d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "60489c1ff8c5d1633fc4837d4f8019623d4e1940", 
+        "git_revision": "d9d99f32762975a370f1abd34a3512bd6fe29111", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "43de6ab8b9790809ac7b4d80bf060a2976a88417", 
+    "revision": "a1b18f9a9e869b1ae261a064a7dd174d59169fb9", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="05a36844c1046a1eb07d5b1325f85ed741f961ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="60489c1ff8c5d1633fc4837d4f8019623d4e1940"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -293,16 +293,18 @@ CameraControlImpl::OnUserError(CameraCon
     "StartCamera",
     "StopCamera",
     "AutoFocus",
     "StartFaceDetection",
     "StopFaceDetection",
     "TakePicture",
     "StartRecording",
     "StopRecording",
+    "PauseRecording",
+    "ResumeRecording",
     "SetConfiguration",
     "StartPreview",
     "StopPreview",
     "SetPictureSize",
     "SetThumbnailSize",
     "ResumeContinuousFocus",
     "Unspecified"
   };
@@ -598,16 +600,58 @@ CameraControlImpl::StopRecording()
       return mCameraControl->StopRecordingImpl();
     }
   };
 
   return Dispatch(new Message(this, CameraControlListener::kInStopRecording));
 }
 
 nsresult
+CameraControlImpl::PauseRecording()
+{
+  class Message : public ControlMessage
+  {
+  public:
+    Message(CameraControlImpl* aCameraControl,
+            CameraControlListener::UserContext aContext)
+      : ControlMessage(aCameraControl, aContext)
+    { }
+
+    nsresult
+    RunImpl() override
+    {
+      return mCameraControl->PauseRecordingImpl();
+    }
+  };
+
+  return Dispatch(new Message(this, CameraControlListener::kInPauseRecording));
+}
+
+nsresult
+CameraControlImpl::ResumeRecording()
+{
+  class Message : public ControlMessage
+  {
+  public:
+    Message(CameraControlImpl* aCameraControl,
+            CameraControlListener::UserContext aContext)
+      : ControlMessage(aCameraControl, aContext)
+    { }
+
+    nsresult
+    RunImpl() override
+    {
+      return mCameraControl->ResumeRecordingImpl();
+    }
+  };
+
+  return Dispatch(new Message(this, CameraControlListener::kInResumeRecording));
+}
+
+nsresult
 CameraControlImpl::StartPreview()
 {
   class Message : public ControlMessage
   {
   public:
     Message(CameraControlImpl* aCameraControl,
             CameraControlListener::UserContext aContext)
       : ControlMessage(aCameraControl, aContext)
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -43,16 +43,18 @@ public:
   virtual nsresult StopPreview() override;
   virtual nsresult AutoFocus() override;
   virtual nsresult StartFaceDetection() override;
   virtual nsresult StopFaceDetection() override;
   virtual nsresult TakePicture() override;
   virtual nsresult StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
                                   const StartRecordingOptions* aOptions) override;
   virtual nsresult StopRecording() override;
+  virtual nsresult PauseRecording() override;
+  virtual nsresult ResumeRecording() override;
   virtual nsresult ResumeContinuousFocus() override;
 
   // Event handlers called directly from outside this class.
   void OnShutter();
   void OnUserError(CameraControlListener::UserContext aContext, nsresult aError);
   void OnSystemError(CameraControlListener::SystemContext aContext, nsresult aError);
   void OnAutoFocusMoving(bool aIsMoving);
 
@@ -116,16 +118,18 @@ protected:
   virtual nsresult StopPreviewImpl() = 0;
   virtual nsresult AutoFocusImpl() = 0;
   virtual nsresult StartFaceDetectionImpl() = 0;
   virtual nsresult StopFaceDetectionImpl() = 0;
   virtual nsresult TakePictureImpl() = 0;
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions) = 0;
   virtual nsresult StopRecordingImpl() = 0;
+  virtual nsresult PauseRecordingImpl() = 0;
+  virtual nsresult ResumeRecordingImpl() = 0;
   virtual nsresult ResumeContinuousFocusImpl() = 0;
   virtual nsresult PushParametersImpl() = 0;
   virtual nsresult PullParametersImpl() = 0;
 
   void OnShutterInternal();
   void OnClosedInternal();
 
   CameraControlListener::CameraListenerConfiguration mCurrentConfiguration;
--- a/dom/camera/CameraControlListener.h
+++ b/dom/camera/CameraControlListener.h
@@ -59,16 +59,18 @@ public:
     kPreviewStarted
   };
   virtual void OnPreviewStateChange(PreviewState aState) { }
 
   enum RecorderState
   {
     kRecorderStopped,
     kRecorderStarted,
+    kRecorderPaused,
+    kRecorderResumed,
     kPosterCreated,
     kPosterFailed,
 #ifdef MOZ_B2G_CAMERA
     kFileSizeLimitReached,
     kVideoLengthLimitReached,
     kTrackCompleted,
     kTrackFailed,
     kMediaRecorderFailed,
@@ -104,16 +106,18 @@ public:
     kInStartCamera,
     kInStopCamera,
     kInAutoFocus,
     kInStartFaceDetection,
     kInStopFaceDetection,
     kInTakePicture,
     kInStartRecording,
     kInStopRecording,
+    kInPauseRecording,
+    kInResumeRecording,
     kInSetConfiguration,
     kInStartPreview,
     kInStopPreview,
     kInSetPictureSize,
     kInSetThumbnailSize,
     kInResumeContinuousFocus,
     kInUnspecified
   };
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -886,16 +886,34 @@ nsDOMCameraControl::StopRecording(ErrorR
   THROW_IF_NO_CAMERACONTROL();
 
   ReleaseAudioChannelAgent();
   mRecording = false;
   aRv = mCameraControl->StopRecording();
 }
 
 void
+nsDOMCameraControl::PauseRecording(ErrorResult& aRv)
+{
+  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  THROW_IF_NO_CAMERACONTROL();
+
+  aRv = mCameraControl->PauseRecording();
+}
+
+void
+nsDOMCameraControl::ResumeRecording(ErrorResult& aRv)
+{
+  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  THROW_IF_NO_CAMERACONTROL();
+
+  aRv = mCameraControl->ResumeRecording();
+}
+
+void
 nsDOMCameraControl::ResumePreview(ErrorResult& aRv)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   THROW_IF_NO_CAMERACONTROL();
   aRv = mCameraControl->StartPreview();
 }
 
 already_AddRefed<Promise>
@@ -1395,16 +1413,24 @@ nsDOMCameraControl::OnRecorderStateChang
       break;
 
     case CameraControlListener::kPosterFailed:
       state = NS_LITERAL_STRING("PosterFailed");
       mOptions.mPosterFilepath.Truncate();
       mOptions.mPosterStorageArea = nullptr;
       break;
 
+    case CameraControlListener::kRecorderPaused:
+      state = NS_LITERAL_STRING("Paused");
+      break;
+
+    case CameraControlListener::kRecorderResumed:
+      state = NS_LITERAL_STRING("Resumed");
+      break;
+
 #ifdef MOZ_B2G_CAMERA
     case CameraControlListener::kFileSizeLimitReached:
       state = NS_LITERAL_STRING("FileSizeLimitReached");
       break;
 
     case CameraControlListener::kVideoLengthLimitReached:
       state = NS_LITERAL_STRING("VideoLengthLimitReached");
       break;
@@ -1651,16 +1677,28 @@ nsDOMCameraControl::OnUserError(CameraCo
       return;
 
     case CameraControlListener::kInStopRecording:
       // This method doesn't have any callbacks, so all we can do is log the
       // failure. This only happens after the hardware has been released.
       NS_WARNING("Failed to stop recording");
       return;
 
+    case CameraControlListener::kInPauseRecording:
+      // This method doesn't have any callbacks, so all we can do is log the
+      // failure. This only happens after the hardware has been released.
+      NS_WARNING("Failed to pause recording");
+      return;
+
+    case CameraControlListener::kInResumeRecording:
+      // This method doesn't have any callbacks, so all we can do is log the
+      // failure. This only happens after the hardware has been released.
+      NS_WARNING("Failed to resume recording");
+      return;
+
     case CameraControlListener::kInStartPreview:
       // This method doesn't have any callbacks, so all we can do is log the
       // failure. This only happens after the hardware has been released.
       NS_WARNING("Failed to (re)start preview");
       return;
 
     case CameraControlListener::kInStopPreview:
       // This method doesn't have any callbacks, so all we can do is log the
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -115,16 +115,18 @@ public:
   void StopFaceDetection(ErrorResult& aRv);
   already_AddRefed<dom::Promise> TakePicture(const dom::CameraPictureOptions& aOptions,
                                              ErrorResult& aRv);
   already_AddRefed<dom::Promise> StartRecording(const dom::CameraStartRecordingOptions& aOptions,
                                                 nsDOMDeviceStorage& storageArea,
                                                 const nsAString& filename,
                                                 ErrorResult& aRv);
   void StopRecording(ErrorResult& aRv);
+  void PauseRecording(ErrorResult& aRv);
+  void ResumeRecording(ErrorResult& aRv);
   void ResumePreview(ErrorResult& aRv);
   already_AddRefed<dom::Promise> ReleaseHardware(ErrorResult& aRv);
   void ResumeContinuousFocus(ErrorResult& aRv);
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   operator nsISupports*() { return static_cast<DOMMediaStream*>(this); }
 
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -1319,16 +1319,58 @@ nsGonkCameraControl::StopRecordingImpl()
     }
   }
 
   // notify DeviceStorage that the new video file is closed and ready
   return NS_DispatchToMainThread(new RecordingComplete(mVideoFile.forget()));
 }
 
 nsresult
+nsGonkCameraControl::PauseRecordingImpl()
+{
+  ReentrantMonitorAutoEnter mon(mRecorderMonitor);
+
+#ifdef MOZ_WIDGET_GONK
+  if (!mRecorder) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  int err = mRecorder->pause();
+  switch (err) {
+    case OK:
+      break;
+    case INVALID_OPERATION:
+      return NS_ERROR_NOT_IMPLEMENTED;
+    default:
+      return NS_ERROR_FAILURE;
+  }
+#endif
+  OnRecorderStateChange(CameraControlListener::kRecorderPaused);
+  return NS_OK;
+}
+
+nsresult
+nsGonkCameraControl::ResumeRecordingImpl()
+{
+  ReentrantMonitorAutoEnter mon(mRecorderMonitor);
+
+#ifdef MOZ_WIDGET_GONK
+  if (!mRecorder) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  if (mRecorder->resume() != OK) {
+    return NS_ERROR_FAILURE;
+  }
+#endif
+  OnRecorderStateChange(CameraControlListener::kRecorderResumed);
+  return NS_OK;
+}
+
+nsresult
 nsGonkCameraControl::ResumeContinuousFocusImpl()
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
   RETURN_IF_NO_CAMERA_HW();
 
   DOM_CAMERA_LOGI("Resuming continuous autofocus\n");
 
   // see
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -133,16 +133,18 @@ protected:
   virtual nsresult StopPreviewImpl() override;
   virtual nsresult AutoFocusImpl() override;
   virtual nsresult StartFaceDetectionImpl() override;
   virtual nsresult StopFaceDetectionImpl() override;
   virtual nsresult TakePictureImpl() override;
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions = nullptr) override;
   virtual nsresult StopRecordingImpl() override;
+  virtual nsresult PauseRecordingImpl() override;
+  virtual nsresult ResumeRecordingImpl() override;
   virtual nsresult ResumeContinuousFocusImpl() override;
   virtual nsresult PushParametersImpl() override;
   virtual nsresult PullParametersImpl() override;
 
   nsresult SetupRecording(int aFd, int aRotation, uint64_t aMaxFileSizeBytes,
                           uint64_t aMaxVideoLengthMs);
   nsresult SetupRecordingFlash(bool aAutoEnableLowLightTorch);
   nsresult SelectCaptureAndPreviewSize(const Size& aPreviewSize, const Size& aCaptureSize,
--- a/dom/camera/GonkRecorder.cpp
+++ b/dom/camera/GonkRecorder.cpp
@@ -15,16 +15,17 @@
  * limitations under the License.
  */
 
 #include "nsDebug.h"
 #define DOM_CAMERA_LOG_LEVEL        3
 #include "CameraCommon.h"
 #include "GonkCameraSource.h"
 #include "GonkRecorder.h"
+#include "mozilla/CondVar.h"
 
 #define RE_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 #define RE_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 #define RE_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 #define RE_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 #define RE_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 
 #include <binder/IPCThreadState.h>
@@ -53,16 +54,142 @@
 #include <unistd.h>
 
 #include <cutils/properties.h>
 #include <system/audio.h>
 
 #define RES_720P (720 * 1280)
 namespace android {
 
+struct GonkRecorder::WrappedMediaSource : MediaSource {
+public:
+    WrappedMediaSource(const sp<MediaSource> &encoder);
+    status_t start(MetaData *params = NULL) override;
+    status_t stop() override;
+    sp<MetaData> getFormat() override;
+    status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL) override;
+    void block();
+    status_t resume();
+
+protected:
+    virtual ~WrappedMediaSource() {};
+
+private:
+    WrappedMediaSource(const WrappedMediaSource &);
+    WrappedMediaSource &operator=(const WrappedMediaSource &);
+
+    sp<MediaSource> mEncoder;
+    mozilla::Mutex mMutex;
+    mozilla::CondVar mCondVar;
+    bool mWait;
+    bool mResume;
+    status_t mResumeStatus;
+};
+
+GonkRecorder::WrappedMediaSource::WrappedMediaSource(const sp<MediaSource> &encoder)
+    : mEncoder(encoder)
+    , mMutex("GonkRecorder::WrappedMediaSource::mMutex")
+    , mCondVar(mMutex, "GonkRecorder::WrappedMediaSource::mCondVar")
+    , mWait(false)
+    , mResume(false)
+    , mResumeStatus(UNKNOWN_ERROR)
+{
+}
+
+status_t
+GonkRecorder::WrappedMediaSource::start(MetaData *params)
+{
+    return mEncoder->start(params);
+}
+
+status_t
+GonkRecorder::WrappedMediaSource::stop()
+{
+    {
+      // Ensure the writer thread is not blocked first.
+      MutexAutoLock lock(mMutex);
+      mWait = false;
+      mCondVar.Notify();
+    }
+    return mEncoder->stop();
+}
+
+sp<MetaData>
+GonkRecorder::WrappedMediaSource::getFormat()
+{
+    return mEncoder->getFormat();
+}
+
+status_t
+GonkRecorder::WrappedMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
+{
+    MutexAutoLock lock(mMutex);
+    while (mWait) {
+      mCondVar.Wait();
+    }
+
+    status_t rv = UNKNOWN_ERROR;
+    MediaBuffer *buf = NULL;
+
+    do {
+        rv = mEncoder->read(&buf, options);
+        if (!mResume) {
+            break;
+        }
+
+        if (rv != OK || !buf) {
+            mResume = false;
+            mResumeStatus = UNKNOWN_ERROR;
+            mCondVar.Notify();
+            break;
+        }
+
+        int32_t isSync = 0;
+        buf->meta_data()->findInt32(kKeyIsSyncFrame, &isSync);
+        if (isSync) {
+            mResume = false;
+            mResumeStatus = OK;
+            mCondVar.Notify();
+            break;
+        }
+
+        buf->release();
+        buf = NULL;
+    } while(true);
+
+    *buffer = buf;
+    return rv;
+}
+
+void
+GonkRecorder::WrappedMediaSource::block()
+{
+    MutexAutoLock lock(mMutex);
+    mWait = true;
+}
+
+status_t
+GonkRecorder::WrappedMediaSource::resume()
+{
+    MutexAutoLock lock(mMutex);
+    if (!mWait) {
+        return UNKNOWN_ERROR;
+    }
+
+    mWait = false;
+    mResume = true;
+    mCondVar.Notify();
+
+    do {
+        mCondVar.Wait();
+    } while(mResume);
+
+    return mResumeStatus;
+}
+
 GonkRecorder::GonkRecorder()
     : mWriter(NULL),
       mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mStarted(false) {
 
     RE_LOGV("Constructor");
@@ -1495,37 +1622,42 @@ status_t GonkRecorder::setupAudioEncoder
     return OK;
 }
 
 status_t GonkRecorder::setupMPEG4Recording(
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
         int32_t *totalBitRate,
-        sp<MediaWriter> *mediaWriter) {
+        sp<MediaWriter> *mediaWriter,
+        sp<WrappedMediaSource> *mediaSource) {
     mediaWriter->clear();
     *totalBitRate = 0;
     status_t err = OK;
     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
+    sp<WrappedMediaSource> writerSource;
 
     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
 
         sp<MediaSource> mediaSource;
         err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
         err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
         if (err != OK) {
             return err;
         }
 
-        writer->addSource(encoder);
+        sp<GonkCameraSource> cameraSource = reinterpret_cast<GonkCameraSource *>(mediaSource.get());
+        writerSource = new WrappedMediaSource(encoder);
+
+        writer->addSource(writerSource);
         *totalBitRate += videoBitRate;
     }
 
     // Audio source is added at the end if it exists.
     // This help make sure that the "recoding" sound is suppressed for
     // camcorder applications in the recorded files.
     if (mAudioSource != AUDIO_SOURCE_CNT) {
         err = setupAudioEncoder(writer);
@@ -1551,16 +1683,17 @@ status_t GonkRecorder::setupMPEG4Recordi
     mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
     if (mStartTimeOffsetMs > 0) {
         reinterpret_cast<MPEG4Writer *>(writer.get())->
             setStartTimeOffsetMs(mStartTimeOffsetMs);
     }
 
     writer->setListener(mListener);
     *mediaWriter = writer;
+    *mediaSource = writerSource;
     return OK;
 }
 
 void GonkRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
         sp<MetaData> *meta) {
     (*meta)->setInt64(kKeyTime, startTimeUs);
     (*meta)->setInt32(kKeyFileType, mOutputFormat);
     (*meta)->setInt32(kKeyBitRate, totalBitRate);
@@ -1582,17 +1715,18 @@ void GonkRecorder::setupMPEG4MetaData(in
         (*meta)->setInt32(kKeyRotation, mRotationDegrees);
     }
 }
 
 status_t GonkRecorder::startMPEG4Recording() {
     int32_t totalBitRate;
     status_t err = setupMPEG4Recording(
             mOutputFd, mVideoWidth, mVideoHeight,
-            mVideoBitRate, &totalBitRate, &mWriter);
+            mVideoBitRate, &totalBitRate, &mWriter,
+            &mWriterSource);
     if (err != OK) {
         return err;
     }
 
     //systemTime() doesn't give correct time because
     //HAVE_POSIX_CLOCKS is not defined for utils/Timers.cpp
     //so, using clock_gettime directly
 #include <time.h>
@@ -1611,30 +1745,66 @@ status_t GonkRecorder::startMPEG4Recordi
     return OK;
 }
 
 status_t GonkRecorder::pause() {
     RE_LOGV("pause");
     if (mWriter == NULL) {
         return UNKNOWN_ERROR;
     }
-    mWriter->pause();
-
-    if (mStarted) {
+    if (!mStarted) {
+        return OK;
+    }
+    // Pause is not properly supported by all writers although
+    // for B2G we only currently use 3GPP/MPEG4
+    int err = INVALID_OPERATION;
+    switch (mOutputFormat) {
+        case OUTPUT_FORMAT_DEFAULT:
+        case OUTPUT_FORMAT_THREE_GPP:
+        case OUTPUT_FORMAT_MPEG_4:
+            err = mWriter->pause();
+            break;
+        default:
+            break;
+    }
+    if (err == OK) {
         mStarted = false;
     }
-
+    return err;
+}
 
-    return OK;
+status_t GonkRecorder::resume() {
+    RE_LOGV("resume");
+    if (mWriter == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    if (mStarted) {
+        return OK;
+    }
+    /* While the writer is paused, it will continue to pull frames
+       from the encoder. This ensures continuity on the timestamps of
+       the encoded frames, etc. When we want to resume however, we must
+       ensure that the first read frame is a key frame. */
+    mWriterSource->block();
+    int err = mWriter->start(NULL);
+    if (err != OK) {
+        return err;
+    }
+    err = mWriterSource->resume();
+    if (err == OK) {
+      mStarted = true;
+    }
+    return err;
 }
 
 status_t GonkRecorder::stop() {
     RE_LOGV("stop");
     status_t err = OK;
 
+    mWriterSource.clear();
     if (mWriter != NULL) {
         err = mWriter->stop();
         mWriter.clear();
     }
 
     if (mOutputFd >= 0) {
         ::close(mOutputFd);
         mOutputFd = -1;
--- a/dom/camera/GonkRecorder.h
+++ b/dom/camera/GonkRecorder.h
@@ -58,31 +58,35 @@ struct GonkRecorder {
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
     virtual status_t setCamera(const sp<GonkCameraHardware>& aCameraHw);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t setClientName(const String16& clientName);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t pause();
+    virtual status_t resume();
     virtual status_t stop();
     virtual status_t close();
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
     virtual status_t dump(int fd, const Vector<String16>& args) const;
     // Querying a SurfaceMediaSourcer
 
 protected:
     virtual ~GonkRecorder();
 
 private:
+    struct WrappedMediaSource;
+
     sp<IMediaRecorderClient> mListener;
     String16 mClientName;
     uid_t mClientUid;
     sp<MediaWriter> mWriter;
+    sp<WrappedMediaSource> mWriterSource;
     int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
     audio_source_t mAudioSource;
     video_source mVideoSource;
     output_format mOutputFormat;
     audio_encoder mAudioEncoder;
     video_encoder mVideoEncoder;
@@ -122,17 +126,18 @@ private:
 
     sp<GonkCameraHardware> mCameraHw;
 
     status_t setupMPEG4Recording(
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
         int32_t *totalBitRate,
-        sp<MediaWriter> *mediaWriter);
+        sp<MediaWriter> *mediaWriter,
+        sp<WrappedMediaSource> *mediaSource);
     void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
         sp<MetaData> *meta);
     status_t startMPEG4Recording();
     status_t startAMRRecording();
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     status_t startAACRecording();
 #endif
     status_t startRawAudioRecording();
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -251,16 +251,18 @@ public:
   virtual nsresult SetConfiguration(const Configuration& aConfig) = 0;
   virtual nsresult StartPreview() = 0;
   virtual nsresult StopPreview() = 0;
   virtual nsresult AutoFocus() = 0;
   virtual nsresult TakePicture() = 0;
   virtual nsresult StartRecording(DeviceStorageFileDescriptor* aFileDescriptor,
                                   const StartRecordingOptions* aOptions = nullptr) = 0;
   virtual nsresult StopRecording() = 0;
+  virtual nsresult PauseRecording() = 0;
+  virtual nsresult ResumeRecording() = 0;
   virtual nsresult StartFaceDetection() = 0;
   virtual nsresult StopFaceDetection() = 0;
   virtual nsresult ResumeContinuousFocus() = 0;
 
   // Camera parameter getters and setters. 'aKey' must be one of the
   // CAMERA_PARAM_* values enumerated above.
   //
   // Return values:
--- a/dom/camera/test/camera_common.js
+++ b/dom/camera/test/camera_common.js
@@ -75,16 +75,18 @@ function CameraTestSuite() {
   this.expectedRejectStopRecording = this._expectedRejectStopRecording.bind(this);
   this.rejectGetCamera = this._rejectGetCamera.bind(this);
   this.rejectConfigure = this._rejectConfigure.bind(this);
   this.rejectRelease = this._rejectRelease.bind(this);
   this.rejectAutoFocus = this._rejectAutoFocus.bind(this);
   this.rejectTakePicture = this._rejectTakePicture.bind(this);
   this.rejectStartRecording = this._rejectStartRecording.bind(this);
   this.rejectStopRecording = this._rejectStopRecording.bind(this);
+  this.rejectPauseRecording = this._rejectPauseRecording.bind(this);
+  this.rejectResumeRecording = this._rejectResumeRecording.bind(this);
   this.rejectPreviewStarted = this._rejectPreviewStarted.bind(this);
 
   var self = this;
   this._window.addEventListener('beforeunload', function() {
     if (isDefinedObj(self.viewfinder)) {
       self.viewfinder.srcObject = null;
     }
 
@@ -404,16 +406,24 @@ CameraTestSuite.prototype = {
   _rejectStartRecording: function(e) {
     return this.logError('start recording failed', e);
   },
 
   _rejectStopRecording: function(e) {
     return this.logError('stop recording failed', e);
   },
 
+  _rejectPauseRecording: function(e) {
+    return this.logError('pause recording failed', e);
+  },
+
+  _rejectResumeRecording: function(e) {
+    return this.logError('resume recording failed', e);
+  },
+
   _rejectPreviewStarted: function(e) {
     return this.logError('preview start failed', e);
   },
 
   /* The success handlers below are intended to be used
      when a test case does not expect a particular call
      to succed but otherwise does not require any special
      handling of that situation beyond failing the test
--- a/dom/camera/test/test_camera_record.html
+++ b/dom/camera/test/test_camera_record.html
@@ -40,16 +40,60 @@ suite.test('recording', function() {
       }
       suite.camera.addEventListener('recorderstatechange', onEvent);
     });
 
     var domPromise = suite.camera.startRecording({}, storage, testFilePath);
     return Promise.all([domPromise, eventPromise]);
   }
 
+  function pauseRecording(p) {
+    var eventPromise = new Promise(function(resolve, reject) {
+      function onEvent(evt) {
+        ok(evt.newState === 'Paused', 'recorder state change event = ' + evt.newState);
+        suite.camera.removeEventListener('recorderstatechange', onEvent);
+        resolve();
+      }
+      suite.camera.addEventListener('recorderstatechange', onEvent);
+    });
+
+    var domPromise = new Promise(function(resolve, reject) {
+      try {
+        suite.camera.pauseRecording();
+        resolve();
+      } catch(e) {
+        reject(e);
+      }
+    });
+
+    return Promise.all([domPromise, eventPromise]);
+  }
+
+  function resumeRecording(p) {
+    var eventPromise = new Promise(function(resolve, reject) {
+      function onEvent(evt) {
+        ok(evt.newState === 'Resumed', 'recorder state change event = ' + evt.newState);
+        suite.camera.removeEventListener('recorderstatechange', onEvent);
+        resolve();
+      }
+      suite.camera.addEventListener('recorderstatechange', onEvent);
+    });
+
+    var domPromise = new Promise(function(resolve, reject) {
+      try {
+        suite.camera.resumeRecording();
+        resolve();
+      } catch(e) {
+        reject(e);
+      }
+    });
+
+    return Promise.all([domPromise, eventPromise]);
+  }
+
   function stopRecording(p) {
     var eventPromise = new Promise(function(resolve, reject) {
       function onEvent(evt) {
         ok(evt.newState === 'Stopped', 'recorder state change event = ' + evt.newState);
         suite.camera.removeEventListener('recorderstatechange', onEvent);
         resolve();
       }
       suite.camera.addEventListener('recorderstatechange', onEvent);
@@ -65,17 +109,19 @@ suite.test('recording', function() {
     });
 
     return Promise.all([domPromise, eventPromise]);
   }
 
   return suite.getCamera(undefined, baseConfig)
     .then(cleanup, suite.rejectGetCamera)
     .then(startRecording)
-    .then(stopRecording, suite.rejectStartRecording)
+    .then(pauseRecording, suite.rejectStartRecording)
+    .then(resumeRecording, suite.rejectPauseRecording)
+    .then(stopRecording, suite.rejectResumeRecording)
     .catch(suite.rejectStopRecording);
 });
 
 // bug 1152500
 suite.test('interrupt-record', function() {
   function startRecording(p) {
     var startPromise = suite.camera.startRecording({}, storage, testFilePath);
     suite.camera.stopRecording();
--- a/dom/webidl/CameraControl.webidl
+++ b/dom/webidl/CameraControl.webidl
@@ -244,17 +244,29 @@ interface CameraControl : MediaStream
   */
   attribute EventHandler    onclose;
 
   /* the event dispatched when the recorder changes state, either because
      the recording process encountered an error, or because one of the
      recording limits (see CameraStartRecordingOptions) was reached.
 
      event type is CameraStateChangeEvent where:
-         'newState' is the new recorder state */
+         'newState' is one of the following states:
+             'Started' if the recording has begun capturing data
+             'Stopped' when the recording has completed (success and failure)
+             'Paused' if the recording is paused
+             'Resumed' if the recording is resumed after pausing
+             'PosterCreated' if a poster was requested and created
+             'PosterFailed' if a poster was requested and failed to create
+             'FileSizeLimitReached' if stopped due to file size limit
+             'VideoLengthLimitReached' if stopped due to a time limit
+             'TrackCompleted' if audio or video track complete when stopping
+             'TrackFailed' if audio or video track incomplete when stopping
+             'MediaRecorderFailed' if failed due to local error
+             'MediaServerFailed' if failed due to media server
   attribute EventHandler    onrecorderstatechange;
 
   /* the event dispatched when the viewfinder stops or starts,
      useful for synchronizing other UI elements.
 
      event type is CameraStateChangeEvent where:
          'newState' is the new preview state */
   attribute EventHandler    onpreviewstatechange;
@@ -341,20 +353,31 @@ interface CameraControl : MediaStream
   /* start recording video; 'options' is a CameraStartRecordingOptions object.
      If the success/error callbacks are not used, one may determine success by
      waiting for the recorderstatechange event. */
   [Throws]
   Promise<void> startRecording(CameraStartRecordingOptions options,
                                DeviceStorage storageArea,
                                DOMString filename);
 
-  /* stop precording video. */
+  /* stop recording video. */
   [Throws]
   void stopRecording();
 
+  /* pause recording video. The camera remains active but audio and video
+     frames are no longer saved in the output file. If called when not
+     recording or already paused, it fails silently. */
+  [Throws]
+  void pauseRecording();
+
+  /* resume recording video while paused. If called when not recording or
+     not paused, it fails silently. */
+  [Throws]
+  void resumeRecording();
+
   /* call in or after the takePicture() onSuccess callback to
      resume the camera preview stream. */
   [Throws]
   void resumePreview();
 
   /* release the camera so that other applications can use it; you should
      probably call this whenever the camera is not longer in the foreground
      (depending on your usage model).
--- a/testing/docker/builder/Dockerfile
+++ b/testing/docker/builder/Dockerfile
@@ -16,16 +16,16 @@ RUN hg clone http://hg.mozilla.org/build
       cd /tools/tools && \
       python setup.py install
 
 # Initialize git (makes repo happy)
 RUN git config --global user.email "mozilla@example.com" && \
     git config --global user.name "mozilla"
 
 # VCS Tools
-RUN npm install -g taskcluster-vcs@2.3.6
+RUN npm install -g taskcluster-vcs@2.3.8
 
 # TODO enable worker
 # TODO volume mount permissions will be an issue
 # USER worker
 
 COPY bin /home/worker/bin
 RUN chmod a+x /home/worker/bin/*
--- a/testing/docker/builder/VERSION
+++ b/testing/docker/builder/VERSION
@@ -1,1 +1,1 @@
-0.5.6
+0.5.7
--- a/testing/docker/desktop-build/Dockerfile
+++ b/testing/docker/desktop-build/Dockerfile
@@ -1,9 +1,9 @@
-FROM          quay.io/djmitche/ubuntu-build:0.0.4
+FROM          taskcluster/ubuntu-build:0.0.5
 MAINTAINER    Morgan Reece Phillips <winter2718@gmail.com>
 
 # Add build scripts; these are the entry points from the taskcluster worker, and
 # operate on environment variables
 ADD             bin /home/worker/bin
 RUN             chmod +x /home/worker/bin/*
 
 # Add custom mozharness configs
--- a/testing/docker/desktop-build/REGISTRY
+++ b/testing/docker/desktop-build/REGISTRY
@@ -1,1 +1,1 @@
-quay.io/djmitche
+taskcluster
--- a/testing/docker/desktop-build/VERSION
+++ b/testing/docker/desktop-build/VERSION
@@ -1,1 +1,1 @@
-0.0.22
+0.0.23
--- a/testing/docker/desktop32-build/Dockerfile
+++ b/testing/docker/desktop32-build/Dockerfile
@@ -1,9 +1,9 @@
-FROM          quay.io/djmitche/ubuntu32-build:0.0.4
+FROM          taskcluster/ubuntu32-build:0.0.5
 MAINTAINER    Morgan Reece Phillips <winter2718@gmail.com>
 
 # Add build scripts; these are the entry points from the taskcluster worker, and
 # operate on environment variables
 ADD                 bin /home/worker/bin
 RUN                 chmod +x /home/worker/bin/*
 
 ##
--- a/testing/docker/desktop32-build/REGISTRY
+++ b/testing/docker/desktop32-build/REGISTRY
@@ -1,1 +1,1 @@
-quay.io/djmitche
+taskcluster
--- a/testing/docker/desktop32-build/VERSION
+++ b/testing/docker/desktop32-build/VERSION
@@ -1,1 +1,1 @@
-0.0.2
+0.0.3
--- a/testing/docker/tester-device/Dockerfile
+++ b/testing/docker/tester-device/Dockerfile
@@ -26,17 +26,17 @@ RUN apt-get upgrade -y && apt-get instal
 RUN curl https://bootstrap.pypa.io/get-pip.py | python
 RUN pip install virtualenv
 
 RUN git config --global user.email "mozilla@example.com" && \
     git config --global user.name "mozilla"
 
 
 # Get node packages
-RUN npm install -g taskcluster-vcs@2.3.1
+RUN npm install -g taskcluster-vcs@2.3.8
 
 WORKDIR /home/worker
 
 ADD bin /home/worker/bin
 ADD data /home/worker/data
 ADD https://raw.githubusercontent.com/taskcluster/buildbot-step/master/buildbot_step /home/worker/bin/buildbot_step
 RUN chmod u+x /home/worker/bin/*
 
--- a/testing/docker/tester-device/VERSION
+++ b/testing/docker/tester-device/VERSION
@@ -1,1 +1,1 @@
-0.0.4
+0.0.5
--- a/testing/docker/tester/Dockerfile
+++ b/testing/docker/tester/Dockerfile
@@ -13,17 +13,17 @@ ADD            https://raw.githubusercon
 COPY           tc-vcs-config.yml /etc/taskcluster-vcs.yml
 
 # Run test setup script
 RUN chmod u+x /home/worker/bin/buildbot_step
 RUN chmod u+x /usr/local/bin/linux64-minidump_stackwalk
 RUN apt-get install -y python-pip && pip install virtualenv;
 RUN mkdir Documents; mkdir Pictures; mkdir Music; mkdir Videos; mkdir artifacts
 RUN npm install -g npm@^2.0.0
-RUN npm install -g taskcluster-vcs@2.3.4
+RUN npm install -g taskcluster-vcs@2.3.8
 RUN npm install -g taskcluster-npm-cache@1.1.14
 RUN rm -Rf .cache && mkdir -p .cache
 ENV PATH $PATH:/home/worker/bin
 
 # Remove once running under 'worker' user.  This is necessary for pulseaudio to start
 # XXX: change this back to worker:worker once permissions issues are resolved
 RUN            chown -R root:root /home/worker
 
--- a/testing/docker/tester/VERSION
+++ b/testing/docker/tester/VERSION
@@ -1,1 +1,1 @@
-0.3.5
+0.3.6
--- a/testing/docker/ubuntu-build/Dockerfile
+++ b/testing/docker/ubuntu-build/Dockerfile
@@ -6,17 +6,17 @@ RUN useradd -d /home/worker -s /bin/bash
 
 # install non-build specific dependencies in a single layer
 ADD           system-setup.sh   /tmp/system-setup.sh
 RUN           bash /tmp/system-setup.sh
 
 # configure git and install tc-vcs
 RUN git config --global user.email "nobody@mozilla.com" && \
     git config --global user.name "mozilla"
-RUN npm install -g taskcluster-vcs@2.3.6
+RUN npm install -g taskcluster-vcs@2.3.8
 
 # Ensure that build specific dependencies live in a single layer
 ADD           build-setup.sh   /tmp/build-setup.sh
 RUN           bash /tmp/build-setup.sh
 
 # Builds need the share module enabled
 ADD           hgrc /home/worker/.hgrc
 
--- a/testing/docker/ubuntu-build/REGISTRY
+++ b/testing/docker/ubuntu-build/REGISTRY
@@ -1,1 +1,1 @@
-quay.io/djmitche
+taskcluster
--- a/testing/docker/ubuntu-build/VERSION
+++ b/testing/docker/ubuntu-build/VERSION
@@ -1,1 +1,1 @@
-0.0.4
+0.0.5
--- a/testing/docker/ubuntu32-build/Dockerfile
+++ b/testing/docker/ubuntu32-build/Dockerfile
@@ -6,17 +6,17 @@ RUN useradd -d /home/worker -s /bin/bash
 
 # install non-build specific dependencies in a single layer
 ADD           system-setup.sh   /tmp/system-setup.sh
 RUN           bash /tmp/system-setup.sh
 
 # configure git and install tc-vcs
 RUN git config --global user.email "nobody@mozilla.com" && \
     git config --global user.name "mozilla"
-RUN npm install -g taskcluster-vcs@2.3.6
+RUN npm install -g taskcluster-vcs@2.3.8
 
 # Ensure that build specific dependencies live in a single layer
 ADD           build-setup.sh   /tmp/build-setup.sh
 RUN           bash /tmp/build-setup.sh
 
 # Builds need the share module enabled
 ADD           hgrc /home/worker/.hgrc
 
--- a/testing/docker/ubuntu32-build/REGISTRY
+++ b/testing/docker/ubuntu32-build/REGISTRY
@@ -1,1 +1,1 @@
-quay.io/djmitche
+taskcluster
--- a/testing/docker/ubuntu32-build/VERSION
+++ b/testing/docker/ubuntu32-build/VERSION
@@ -1,1 +1,1 @@
-0.0.4
+0.0.5