Merge b-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 27 Nov 2014 17:08:41 -0800
changeset 217904 ebdbd84d933dcafc09d6d1b71a321436b14f8527
parent 217879 1d1cbbd46b0dcc9669f5cf8c5a8862e3e73d2b67 (current diff)
parent 217903 8fc03614348dfbb47a679e59d24d6278c6bb9d21 (diff)
child 217916 63abc656b8656a8407015a6f9541bd46719f9759
push id27895
push userphilringnalda@gmail.com
push dateFri, 28 Nov 2014 01:08:57 +0000
treeherderautoland@ebdbd84d933d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b-i to m-c, a=merge
--- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8b13bfc1d7d25cee4de55f332654fdba25b8460b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <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="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "78d735b50d94254ff236fc34a6fbaa5ed27692a0", 
+    "revision": "415520315b048f40979e9bac344bec99e18df901", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <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/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="80bc1445959db79e9d2e947cc56e1eb7b0d3d0f0"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1fff49c664f905f11a86426a9835e6df6b58e825"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/dom/nfc/gonk/Nfc.js
+++ b/dom/nfc/gonk/Nfc.js
@@ -604,27 +604,19 @@ Nfc.prototype = {
      */
     gSystemMessenger.broadcastMessage("nfc-hci-event-transaction", message);
   },
 
   /**
    * Process a message from the gMessageManager.
    */
   receiveMessage: function receiveMessage(message) {
-    let isRFAPI = message.name == "NFC:ChangeRFState";
-    let isSendFile = message.name == "NFC:SendFile";
-    let isInfoAPI = message.name == "NFC:QueryInfo";
-
-    if (!isRFAPI && !isInfoAPI && (this.rfState != NFC.NFC_RF_STATE_DISCOVERY)) {
-      debug("NFC is not enabled. current rfState:" + this.rfState);
-      this.sendNfcErrorResponse(message, NFC.NFC_GECKO_ERROR_NOT_ENABLED);
-      return null;
-    }
-
-    if (!isRFAPI && !isSendFile && !isInfoAPI) {
+      if (["NFC:ChangeRFState",
+           "NFC:SendFile",
+           "NFC:QueryInfo"].indexOf(message.name) == -1) {
       // Update the current sessionId before sending to the NFC service.
       message.data.sessionId = SessionHelper.getId(message.data.sessionToken);
     }
 
     switch (message.name) {
       case "NFC:ChangeRFState":
         this.sendToNfcService("changeRFState", message.data);
         break;
--- a/dom/nfc/gonk/nfc_consts.js
+++ b/dom/nfc/gonk/nfc_consts.js
@@ -21,24 +21,22 @@ this.DEBUG_ALL = false;
 // Set individually to debug specific layers
 this.DEBUG_CONTENT_HELPER = DEBUG_ALL || false;
 this.DEBUG_NFC = DEBUG_ALL || false;
 
 // Gecko specific error codes
 this.NFC_GECKO_SUCCESS = 0;
 this.NFC_GECKO_ERROR_GENERIC_FAILURE = 1;
 this.NFC_GECKO_ERROR_P2P_REG_INVALID = 2;
-this.NFC_GECKO_ERROR_NOT_ENABLED = 3;
-this.NFC_GECKO_ERROR_SEND_FILE_FAILED = 4;
-this.NFC_GECKO_ERROR_BAD_SESSION_TOKEN = 5;
+this.NFC_GECKO_ERROR_SEND_FILE_FAILED = 3;
+this.NFC_GECKO_ERROR_BAD_SESSION_TOKEN = 4;
 
 this.NFC_ERROR_MSG = {};
 this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_GENERIC_FAILURE] = "NfcGenericFailureError";
 this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_P2P_REG_INVALID] = "NfcP2PRegistrationInvalid";
-this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_NOT_ENABLED] = "NfcNotEnabledError";
 this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_SEND_FILE_FAILED] = "NfcSendFileFailed";
 this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_BAD_SESSION_TOKEN] = "NfcBadSessionToken";
 
 this.NFC_RF_STATE_IDLE = "idle";
 this.NFC_RF_STATE_LISTEN = "listen";
 this.NFC_RF_STATE_DISCOVERY = "discovery";
 
 this.TOPIC_MOZSETTINGS_CHANGED      = "mozsettings-changed";
--- a/services/mobileid/MobileIdentityVerificationFlow.jsm
+++ b/services/mobileid/MobileIdentityVerificationFlow.jsm
@@ -32,78 +32,77 @@ MobileIdentityVerificationFlow.prototype
     return this.register()
     .then(
       (registerResult) => {
         log.debug("Register result ${}", registerResult);
         if (!registerResult || !registerResult.msisdnSessionToken) {
           return Promise.reject(ERROR_INTERNAL_UNEXPECTED);
         }
         this.sessionToken = registerResult.msisdnSessionToken;
-        return this._doVerification();
+        // We save the timestamp of the start of the verification timeout to be
+        // able to provide to the UI the remaining time on each retry.
+        if (!this.timer) {
+          log.debug("Creating verification code timer");
+          this.timerCreation = Date.now();
+          this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+          this.timer.initWithCallback(this.onVerificationCodeTimeout.bind(this),
+                                      VERIFICATIONCODE_TIMEOUT,
+                                      this.timer.TYPE_ONE_SHOT);
+        }
+
+        if (!this.verifyStrategy) {
+          return Promise.reject(ERROR_INTERNAL_INVALID_VERIFICATION_FLOW);
+        }
+
+        return this.verifyStrategy()
+        .then(() => {
+          return this._doVerification();
+        }, (reason) => {
+          this.verificationCodeDeferred.reject(reason);
+        });
       }
     )
   },
 
   _doVerification: function() {
     log.debug("_doVerification");
-    // We save the timestamp of the start of the verification timeout to be
-    // able to provide to the UI the remaining time on each retry.
-    if (!this.timer) {
-      log.debug("Creating verification code timer");
-      this.timerCreation = Date.now();
-      this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      this.timer.initWithCallback(this.onVerificationCodeTimeout.bind(this),
-                                  VERIFICATIONCODE_TIMEOUT,
-                                  this.timer.TYPE_ONE_SHOT);
-    }
-
-    if (!this.verifyStrategy) {
-      return Promise.reject(ERROR_INTERNAL_INVALID_VERIFICATION_FLOW);
-    }
 
     this.verificationCodeDeferred = Promise.defer();
 
-    this.verifyStrategy()
-    .then(
-      () => {
-        // If the verification flow can be for an external phone number,
-        // we need to ask the user for the verification code.
-        // In that case we don't do a notification about the verification
-        // process being done until the user enters the verification code
-        // in the UI.
-        if (this.verificationOptions.external) {
-          let timeLeft = 0;
-          if (this.timer) {
-            timeLeft = this.timerCreation + VERIFICATIONCODE_TIMEOUT -
-                       Date.now();
+    // If the verification flow can be for an external phone number,
+    // we need to ask the user for the verification code.
+    // In that case we don't do a notification about the verification
+    // process being done until the user enters the verification code
+    // in the UI.
+    if (this.verificationOptions.external) {
+      let timeLeft = 0;
+      if (this.timer) {
+        timeLeft = this.timerCreation + VERIFICATIONCODE_TIMEOUT -
+                   Date.now();
+      }
+      this.ui.verificationCodePrompt(this.retries,
+                                     VERIFICATIONCODE_TIMEOUT / 1000,
+                                     timeLeft / 1000)
+      .then(
+        (verificationCode) => {
+          if (!verificationCode) {
+            return this.verificationCodeDeferred.reject(
+              ERROR_INTERNAL_INVALID_PROMPT_RESULT);
           }
-          this.ui.verificationCodePrompt(this.retries,
-                                         VERIFICATIONCODE_TIMEOUT / 1000,
-                                         timeLeft / 1000)
-          .then(
-            (verificationCode) => {
-              if (!verificationCode) {
-                return this.verificationCodeDeferred.reject(
-                  ERROR_INTERNAL_INVALID_PROMPT_RESULT);
-              }
-              // If the user got the verification code that means that the
-              // introduced phone number didn't belong to any of the inserted
-              // SIMs.
-              this.ui.verify();
-              this.verificationCodeDeferred.resolve(verificationCode);
-            }
-          );
-        } else {
+          // If the user got the verification code that means that the
+          // introduced phone number didn't belong to any of the inserted
+          // SIMs.
           this.ui.verify();
+          this.verificationCodeDeferred.resolve(verificationCode);
         }
-      },
-      (reason) => {
-        this.verificationCodeDeferred.reject(reason);
-      }
-    );
+      );
+    } else {
+      this.ui.verify();
+    }
+
     return this.verificationCodeDeferred.promise.then(
       this.onVerificationCode.bind(this)
     );
   },
 
   // When we receive a verification code from the UI, we check it against
   // the server. If the verification code is incorrect, we decrease the
   // number of retries left and allow the user to try again. If there is no
@@ -140,18 +139,21 @@ MobileIdentityVerificationFlow.prototype
         return this.verificationOptions;
       },
       (error) => {
         log.error("Verification code error " + error);
         this.retries--;
         log.error("Retries left " + this.retries);
         if (!this.retries) {
           this.ui.error(ERROR_NO_RETRIES_LEFT);
+          this.timer.cancel();
+          this.timer = null;
           return Promise.reject(ERROR_NO_RETRIES_LEFT);
         }
+        this.ui.error(ERROR_INVALID_VERIFICATION_CODE);
         this.verifying = false;
         if (this.queuedTimeout) {
           this.onVerificationCodeTimeout();
         }
         return this._doVerification();
       }
     );
   },
--- a/services/mobileid/tests/xpcshell/head.js
+++ b/services/mobileid/tests/xpcshell/head.js
@@ -1,19 +1,462 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
 "use strict";
 
+const Cm = Components.manager;
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 (function initMobileIdTestingInfrastructure() {
   do_get_profile();
 
   const PREF_FORCE_HTTPS = "services.mobileid.forcehttps";
   Services.prefs.setBoolPref(PREF_FORCE_HTTPS, false);
   Services.prefs.setCharPref("services.mobileid.loglevel", "Debug");
   Services.prefs.setCharPref("services.mobileid.server.uri",
                              "https://dummyurl.com");
 }).call(this);
+
+const DEBUG = false;
+
+const GET_ASSERTION_IPC_MSG = "MobileId:GetAssertion";
+const GET_ASSERTION_RETURN_OK = "MobileId:GetAssertion:Return:OK";
+const GET_ASSERTION_RETURN_KO = "MobileId:GetAssertion:Return:KO";
+
+// === Globals ===
+
+const ORIGIN = "app://afakeorigin";
+const APP_ID = 1;
+const PRINCIPAL = {
+  origin: ORIGIN,
+  appId: APP_ID
+};
+const PHONE_NUMBER = "+34666555444";
+const ANOTHER_PHONE_NUMBER = "+44123123123";
+const VERIFICATION_CODE = "123456";
+const SESSION_TOKEN = "aSessionToken";
+const ICC_ID = "aIccId";
+const ANOTHER_ICC_ID = "anotherIccId";
+const MNC = "aMnc";
+const ANOTHER_MNC = "anotherMnc";
+const MCC = "aMcc";
+const ANOTHER_MCC = "anotherMcc";
+const OPERATOR = "aOperator";
+const ANOTHER_OPERATOR = "anotherOperator";
+const RADIO_INTERFACE = {
+  rilContext: {
+    iccInfo: {
+      iccid: ICC_ID,
+      mcc: MCC,
+      mnc: MNC,
+      msisdn: PHONE_NUMBER,
+      operator: OPERATOR
+    }
+  },
+  voice: {
+    network: {
+      shortName: OPERATOR
+    },
+    roaming: false
+  },
+  data: {
+    network: {
+      shortName: OPERATOR
+    }
+  }
+};
+const ANOTHER_RADIO_INTERFACE = {
+  rilContext: {
+    iccInfo: {
+      iccid: ANOTHER_ICC_ID,
+      mcc: ANOTHER_MCC,
+      mnc: ANOTHER_MNC,
+      msisdn: ANOTHER_PHONE_NUMBER,
+      operator: ANOTHER_OPERATOR
+    }
+  },
+  voice: {
+    network: {
+      shortName: ANOTHER_OPERATOR
+    },
+    roaming: false
+  },
+  data: {
+    network: {
+      shortName: ANOTHER_OPERATOR
+    }
+  }
+};
+
+const INVALID_RADIO_INTERFACE = {
+  rilContext: {
+    iccInfo: {
+      iccid: null,
+      mcc: "",
+      mnc: "",
+      msisdn: "",
+      operator: ""
+    }
+  },
+  voice: {
+    network: {
+      shortName: ""
+    },
+    roaming: undefined
+  },
+  data: {
+    network: {
+      shortName: ""
+    }
+  }
+};
+
+const CERTIFICATE = "eyJhbGciOiJEUzI1NiJ9.eyJsYXN0QXV0aEF0IjoxNDA0NDY5NzkyODc3LCJ2ZXJpZmllZE1TSVNETiI6IiszMTYxNzgxNTc1OCIsInB1YmxpYy1rZXkiOnsiYWxnb3JpdGhtIjoiRFMiLCJ5IjoiNGE5YzkzNDY3MWZhNzQ3YmM2ZjMyNjE0YTg1MzUyZjY5NDcwMDdhNTRkMDAxMDY4OWU5ZjJjZjc0ZGUwYTEwZTRlYjlmNDk1ZGFmZTA0NGVjZmVlNDlkN2YwOGU4ODQyMDJiOTE5OGRhNWZhZWE5MGUzZjRmNzE1YzZjNGY4Yjc3MGYxZTU4YWZhNDM0NzVhYmFiN2VlZGE1MmUyNjk2YzFmNTljNzMzYjFlYzBhNGNkOTM1YWIxYzkyNzAxYjNiYTA5ZDRhM2E2MzNjNTJmZjE2NGYxMWY3OTg1YzlmZjY3ZThmZDFlYzA2NDU3MTdkMjBiNDE4YmM5M2YzYzVkNCIsInAiOiJmZjYwMDQ4M2RiNmFiZmM1YjQ1ZWFiNzg1OTRiMzUzM2Q1NTBkOWYxYmYyYTk5MmE3YThkYWE2ZGMzNGY4MDQ1YWQ0ZTZlMGM0MjlkMzM0ZWVlYWFlZmQ3ZTIzZDQ4MTBiZTAwZTRjYzE0OTJjYmEzMjViYTgxZmYyZDVhNWIzMDVhOGQxN2ViM2JmNGEwNmEzNDlkMzkyZTAwZDMyOTc0NGE1MTc5MzgwMzQ0ZTgyYTE4YzQ3OTMzNDM4Zjg5MWUyMmFlZWY4MTJkNjljOGY3NWUzMjZjYjcwZWEwMDBjM2Y3NzZkZmRiZDYwNDYzOGMyZWY3MTdmYzI2ZDAyZTE3IiwicSI6ImUyMWUwNGY5MTFkMWVkNzk5MTAwOGVjYWFiM2JmNzc1OTg0MzA5YzMiLCJnIjoiYzUyYTRhMGZmM2I3ZTYxZmRmMTg2N2NlODQxMzgzNjlhNjE1NGY0YWZhOTI5NjZlM2M4MjdlMjVjZmE2Y2Y1MDhiOTBlNWRlNDE5ZTEzMzdlMDdhMmU5ZTJhM2NkNWRlYTcwNGQxNzVmOGViZjZhZjM5N2Q2OWUxMTBiOTZhZmIxN2M3YTAzMjU5MzI5ZTQ4MjliMGQwM2JiYzc4OTZiMTViNGFkZTUzZTEzMDg1OGNjMzRkOTYyNjlhYTg5MDQxZjQwOTEzNmM3MjQyYTM4ODk1YzlkNWJjY2FkNGYzODlhZjFkN2E0YmQxMzk4YmQwNzJkZmZhODk2MjMzMzk3YSJ9LCJwcmluY2lwYWwiOiIwMzgxOTgyYS0xZTgzLTI1NjYtNjgzZS05MDRmNDA0NGM1MGRAbXNpc2RuLWRldi5zdGFnZS5tb3phd3MubmV0IiwiaWF0IjoxNDA0NDY5NzgyODc3LCJleHAiOjE0MDQ0OTEzOTI4NzcsImlzcyI6Im1zaXNkbi1kZXYuc3RhZ2UubW96YXdzLm5ldCJ9."
+
+// === Helpers ===
+
+function addPermission(aAction) {
+  let uri = Cc["@mozilla.org/network/io-service;1"]
+              .getService(Ci.nsIIOService)
+              .newURI(ORIGIN, null, null);
+  let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                     .getService(Ci.nsIScriptSecurityManager)
+                     .getAppCodebasePrincipal(uri, APP_ID, false);
+  let pm = Cc["@mozilla.org/permissionmanager;1"]
+             .getService(Ci.nsIPermissionManager);
+  pm.addFromPrincipal(_principal, MOBILEID_PERM, aAction);
+}
+
+function removePermission() {
+  let uri = Cc["@mozilla.org/network/io-service;1"]
+              .getService(Ci.nsIIOService)
+              .newURI(ORIGIN, null, null);
+  let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                     .getService(Ci.nsIScriptSecurityManager)
+                     .getAppCodebasePrincipal(uri, APP_ID, false);
+  let pm = Cc["@mozilla.org/permissionmanager;1"]
+             .getService(Ci.nsIPermissionManager);
+  pm.removeFromPrincipal(_principal, MOBILEID_PERM);
+}
+
+// === Mocks ===
+
+let Mock = function(aOptions) {
+  if (!aOptions) {
+    aOptions = {};
+  }
+  this._options = aOptions;
+  this._spied = {};
+};
+
+Mock.prototype = {
+  _: function(aMethod) {
+    DEBUG && do_print("_ " + aMethod + JSON.stringify(this._spied));
+    let self = this;
+    return {
+      callsLength: function(aNumberOfCalls) {
+        if (aNumberOfCalls == 0) {
+          do_check_eq(self._spied[aMethod], undefined);
+          return;
+        }
+        do_check_eq(self._spied[aMethod].length, aNumberOfCalls);
+      },
+      call: function(aCallNumber) {
+        return {
+          arg: function(aArgNumber, aValue) {
+            let _arg = self._spied[aMethod][aCallNumber - 1][aArgNumber - 1];
+            if (Array.isArray(aValue)) {
+              do_check_eq(_arg.length, aValue.length)
+              for (let i = 0; i < _arg.length; i++) {
+                do_check_eq(_arg[i], aValue[i]);
+              }
+              return;
+            }
+
+            if (typeof aValue === 'object') {
+              do_check_eq(JSON.stringify(_arg), JSON.stringify(aValue));
+              return;
+            }
+
+            do_check_eq(_arg, aValue);
+          }
+        }
+      }
+    }
+  },
+
+  _spy: function(aMethod, aArgs) {
+    DEBUG && do_print(aMethod + " - " + JSON.stringify(aArgs));
+    if (!this._spied[aMethod]) {
+      this._spied[aMethod] = [];
+    }
+    this._spied[aMethod].push(aArgs);
+  },
+
+  getSpiedCalls: function(aMethod) {
+    return this._spied[aMethod];
+  }
+};
+
+// UI Glue mock up.
+let MockUi = function(aOptions) {
+  Mock.call(this, aOptions);
+};
+
+MockUi.prototype = {
+  __proto__: Mock.prototype,
+
+  _startFlowResult: {
+    phoneNumber: PHONE_NUMBER,
+    mcc: MNC
+  },
+
+  _verifyCodePromptResult: {
+    verificationCode: VERIFICATION_CODE
+  },
+
+  startFlow: function() {
+    this._spy("startFlow", arguments);
+    return Promise.resolve(this._options.startFlowResult ||
+                           this._startFlowResult);
+  },
+
+  verificationCodePrompt: function() {
+    this._spy("verifyCodePrompt", arguments);
+    return Promise.resolve(this._options.verificationCodePromptResult ||
+                           this._verifyCodePromptResult);
+  },
+
+  verify: function() {
+    this._spy("verify", arguments);
+  },
+
+  error: function() {
+    this._spy("error", arguments);
+  },
+
+  verified: function() {
+    this._spy("verified", arguments);
+  },
+
+  set oncancel(aCallback) {
+  },
+
+  set onresendcode(aCallback) {
+  }
+};
+
+// Credentials store mock up.
+let MockCredStore = function(aOptions) {
+  Mock.call(this, aOptions);
+};
+
+MockCredStore.prototype = {
+  __proto__: Mock.prototype,
+
+  _getByOriginResult: null,
+
+  _getByMsisdnResult: null,
+
+  _getByIccIdResult: null,
+
+  getByOrigin: function() {
+    this._spy("getByOrigin", arguments);
+    let result = this._getByOriginResult;
+    if (this._options.getByOriginResult) {
+      if (Array.isArray(this._options.getByOriginResult)) {
+        result = this._options.getByOriginResult.length ?
+                 this._options.getByOriginResult.shift() : null;
+      } else {
+        result = this._options.getByOriginResult;
+      }
+    }
+    return Promise.resolve(result);
+  },
+
+  getByMsisdn: function() {
+    this._spy("getByMsisdn", arguments);
+    return Promise.resolve(this._options.getByMsisdnResult ||
+                           this._getByMsisdnResult);
+  },
+
+  getByIccId: function() {
+    this._spy("getByIccId", arguments);
+    return Promise.resolve(this._options.getByIccIdResult ||
+                           this._getByIccIdResult);
+  },
+
+  add: function() {
+    this._spy("add", arguments);
+    return Promise.resolve();
+  },
+
+  setDeviceIccIds: function() {
+    this._spy("setDeviceIccIds", arguments);
+    return Promise.resolve();
+  },
+
+  removeOrigin: function() {
+    this._spy("removeOrigin", arguments);
+    return Promise.resolve();
+  },
+
+  delete: function() {
+    this._spy("delete", arguments);
+    return Promise.resolve();
+  }
+};
+
+// Client mock up.
+let MockClient = function(aOptions) {
+  Mock.call(this, aOptions);
+};
+
+MockClient.prototype = {
+
+  __proto__: Mock.prototype,
+
+  _discoverResult: {
+    verificationMethods: ["sms/mt"],
+    verificationDetails: {
+      "sms/mt": {
+        mtSender: "123",
+        url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
+      }
+    }
+  },
+
+  _registerResult: {
+    msisdnSessionToken: SESSION_TOKEN
+  },
+
+  _smsMtVerifyResult: {},
+
+  _verifyCodeResult: {
+    msisdn: PHONE_NUMBER
+  },
+
+  _signResult: {
+    cert: CERTIFICATE
+  },
+
+  hawk: {
+    now: function() {
+      return Date.now();
+    }
+  },
+
+  discover: function() {
+    this._spy("discover", arguments);
+    return Promise.resolve(this._options.discoverResult ||
+                           this._discoverResult);
+  },
+
+  register: function() {
+    this._spy("register", arguments);
+    return Promise.resolve(this._options.registerResult ||
+                           this._registerResult);
+  },
+
+  smsMtVerify: function() {
+    this._spy("smsMtVerify", arguments);
+    return Promise.resolve(this._options.smsMtVerifyResult ||
+                           this._smsMtVerifyResult);
+  },
+
+  verifyCode: function() {
+    this._spy("verifyCode", arguments);
+    if (this._options.verifyCodeError) {
+      let error = Array.isArray(this._options.verifyCodeError) ?
+                  this._options.verifyCodeError.shift() :
+                  this._options.verifyCodeError;
+      if (!this._options.verifyCodeError.length) {
+        this._options.verifyCodeError = null;
+      }
+      return Promise.reject(error);
+    }
+    return Promise.resolve(this._options.verifyCodeResult ||
+                           this._verifyCodeResult);
+  },
+
+  sign: function() {
+    this._spy("sign", arguments);
+    if (this._options.signError) {
+      let error = Array.isArray(this._options.signError) ?
+                  this._options.signError.shift() :
+                  this._options.signError;
+      return Promise.reject(error);
+    }
+    return Promise.resolve(this._options.signResult || this._signResult);
+  }
+};
+
+// Override MobileIdentityUIGlue.
+const kMobileIdentityUIGlueUUID = "{05df0566-ca8a-4ec7-bc76-78626ebfbe9a}";
+const kMobileIdentityUIGlueContractID =
+  "@mozilla.org/services/mobileid-ui-glue;1";
+
+// Save original factory.
+/*const kMobileIdentityUIGlueFactory =
+  Cm.getClassObject(Cc[kMobileIdentityUIGlueContractID], Ci.nsIFactory);*/
+
+let fakeMobileIdentityUIGlueFactory = {
+  createInstance: function(aOuter, aIid) {
+    return MobileIdentityUIGlue.QueryInterface(aIid);
+  }
+};
+
+// MobileIdentityUIGlue fake component.
+let MobileIdentityUIGlue = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileIdentityUIGlue]),
+
+};
+
+(function registerFakeMobileIdentityUIGlue() {
+  Cm.QueryInterface(Ci.nsIComponentRegistrar)
+    .registerFactory(Components.ID(kMobileIdentityUIGlueUUID),
+                     "MobileIdentityUIGlue",
+                     kMobileIdentityUIGlueContractID,
+                     fakeMobileIdentityUIGlueFactory);
+})();
+
+// The tests rely on having an app registered. Otherwise, it will throw.
+// Override XULAppInfo.
+const XUL_APP_INFO_UUID = Components.ID("{84fdc459-d96d-421c-9bff-a8193233ae75}");
+const XUL_APP_INFO_CONTRACT_ID = "@mozilla.org/xre/app-info;1";
+
+let (XULAppInfo = {
+  vendor: "Mozilla",
+  name: "MobileIdTest",
+  ID: "{230de50e-4cd1-11dc-8314-0800200b9a66}",
+  version: "1",
+  appBuildID: "2007010101",
+  platformVersion: "",
+  platformBuildID: "2007010101",
+  inSafeMode: false,
+  logConsoleErrors: true,
+  OS: "XPCShell",
+  XPCOMABI: "noarch-spidermonkey",
+
+  QueryInterface: XPCOMUtils.generateQI([
+    Ci.nsIXULAppInfo,
+    Ci.nsIXULRuntime,
+  ])
+}) {
+  let XULAppInfoFactory = {
+    createInstance: function (outer, iid) {
+      if (outer != null) {
+        throw Cr.NS_ERROR_NO_AGGREGATION;
+      }
+      return XULAppInfo.QueryInterface(iid);
+    }
+  };
+  Cm.QueryInterface(Ci.nsIComponentRegistrar)
+    .registerFactory(XUL_APP_INFO_UUID,
+                     "XULAppInfo",
+                     XUL_APP_INFO_CONTRACT_ID,
+                     XULAppInfoFactory);
+}
--- a/services/mobileid/tests/xpcshell/test_mobileid_manager.js
+++ b/services/mobileid/tests/xpcshell/test_mobileid_manager.js
@@ -1,442 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-const Cm = Components.manager;
-
 Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/MobileIdentityManager.jsm");
 Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
 
-const DEBUG = false;
-
-const GET_ASSERTION_IPC_MSG = "MobileId:GetAssertion";
-const GET_ASSERTION_RETURN_OK = "MobileId:GetAssertion:Return:OK";
-const GET_ASSERTION_RETURN_KO = "MobileId:GetAssertion:Return:KO";
-
-// === Globals ===
-
-const ORIGIN = "app://afakeorigin";
-const APP_ID = 1;
-const PRINCIPAL = {
-  origin: ORIGIN,
-  appId: APP_ID
-};
-const PHONE_NUMBER = "+34666555444";
-const ANOTHER_PHONE_NUMBER = "+44123123123";
-const VERIFICATION_CODE = "123456";
-const SESSION_TOKEN = "aSessionToken";
-const ICC_ID = "aIccId";
-const ANOTHER_ICC_ID = "anotherIccId";
-const MNC = "aMnc";
-const ANOTHER_MNC = "anotherMnc";
-const MCC = "aMcc";
-const ANOTHER_MCC = "anotherMcc";
-const OPERATOR = "aOperator";
-const ANOTHER_OPERATOR = "anotherOperator";
-const RADIO_INTERFACE = {
-  rilContext: {
-    iccInfo: {
-      iccid: ICC_ID,
-      mcc: MCC,
-      mnc: MNC,
-      msisdn: PHONE_NUMBER,
-      operator: OPERATOR
-    }
-  },
-  voice: {
-    network: {
-      shortName: OPERATOR
-    },
-    roaming: false
-  },
-  data: {
-    network: {
-      shortName: OPERATOR
-    }
-  }
-};
-const ANOTHER_RADIO_INTERFACE = {
-  rilContext: {
-    iccInfo: {
-      iccid: ANOTHER_ICC_ID,
-      mcc: ANOTHER_MCC,
-      mnc: ANOTHER_MNC,
-      msisdn: ANOTHER_PHONE_NUMBER,
-      operator: ANOTHER_OPERATOR
-    }
-  },
-  voice: {
-    network: {
-      shortName: ANOTHER_OPERATOR
-    },
-    roaming: false
-  },
-  data: {
-    network: {
-      shortName: ANOTHER_OPERATOR
-    }
-  }
-};
-
-const INVALID_RADIO_INTERFACE = {
-  rilContext: {
-    iccInfo: {
-      iccid: null,
-      mcc: "",
-      mnc: "",
-      msisdn: "",
-      operator: ""
-    }
-  },
-  voice: {
-    network: {
-      shortName: ""
-    },
-    roaming: undefined
-  },
-  data: {
-    network: {
-      shortName: ""
-    }
-  }
-};
-
-const CERTIFICATE = "eyJhbGciOiJEUzI1NiJ9.eyJsYXN0QXV0aEF0IjoxNDA0NDY5NzkyODc3LCJ2ZXJpZmllZE1TSVNETiI6IiszMTYxNzgxNTc1OCIsInB1YmxpYy1rZXkiOnsiYWxnb3JpdGhtIjoiRFMiLCJ5IjoiNGE5YzkzNDY3MWZhNzQ3YmM2ZjMyNjE0YTg1MzUyZjY5NDcwMDdhNTRkMDAxMDY4OWU5ZjJjZjc0ZGUwYTEwZTRlYjlmNDk1ZGFmZTA0NGVjZmVlNDlkN2YwOGU4ODQyMDJiOTE5OGRhNWZhZWE5MGUzZjRmNzE1YzZjNGY4Yjc3MGYxZTU4YWZhNDM0NzVhYmFiN2VlZGE1MmUyNjk2YzFmNTljNzMzYjFlYzBhNGNkOTM1YWIxYzkyNzAxYjNiYTA5ZDRhM2E2MzNjNTJmZjE2NGYxMWY3OTg1YzlmZjY3ZThmZDFlYzA2NDU3MTdkMjBiNDE4YmM5M2YzYzVkNCIsInAiOiJmZjYwMDQ4M2RiNmFiZmM1YjQ1ZWFiNzg1OTRiMzUzM2Q1NTBkOWYxYmYyYTk5MmE3YThkYWE2ZGMzNGY4MDQ1YWQ0ZTZlMGM0MjlkMzM0ZWVlYWFlZmQ3ZTIzZDQ4MTBiZTAwZTRjYzE0OTJjYmEzMjViYTgxZmYyZDVhNWIzMDVhOGQxN2ViM2JmNGEwNmEzNDlkMzkyZTAwZDMyOTc0NGE1MTc5MzgwMzQ0ZTgyYTE4YzQ3OTMzNDM4Zjg5MWUyMmFlZWY4MTJkNjljOGY3NWUzMjZjYjcwZWEwMDBjM2Y3NzZkZmRiZDYwNDYzOGMyZWY3MTdmYzI2ZDAyZTE3IiwicSI6ImUyMWUwNGY5MTFkMWVkNzk5MTAwOGVjYWFiM2JmNzc1OTg0MzA5YzMiLCJnIjoiYzUyYTRhMGZmM2I3ZTYxZmRmMTg2N2NlODQxMzgzNjlhNjE1NGY0YWZhOTI5NjZlM2M4MjdlMjVjZmE2Y2Y1MDhiOTBlNWRlNDE5ZTEzMzdlMDdhMmU5ZTJhM2NkNWRlYTcwNGQxNzVmOGViZjZhZjM5N2Q2OWUxMTBiOTZhZmIxN2M3YTAzMjU5MzI5ZTQ4MjliMGQwM2JiYzc4OTZiMTViNGFkZTUzZTEzMDg1OGNjMzRkOTYyNjlhYTg5MDQxZjQwOTEzNmM3MjQyYTM4ODk1YzlkNWJjY2FkNGYzODlhZjFkN2E0YmQxMzk4YmQwNzJkZmZhODk2MjMzMzk3YSJ9LCJwcmluY2lwYWwiOiIwMzgxOTgyYS0xZTgzLTI1NjYtNjgzZS05MDRmNDA0NGM1MGRAbXNpc2RuLWRldi5zdGFnZS5tb3phd3MubmV0IiwiaWF0IjoxNDA0NDY5NzgyODc3LCJleHAiOjE0MDQ0OTEzOTI4NzcsImlzcyI6Im1zaXNkbi1kZXYuc3RhZ2UubW96YXdzLm5ldCJ9."
-
-// === Helpers ===
-
-function addPermission(aAction) {
-  let uri = Cc["@mozilla.org/network/io-service;1"]
-              .getService(Ci.nsIIOService)
-              .newURI(ORIGIN, null, null);
-  let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
-                     .getService(Ci.nsIScriptSecurityManager)
-                     .getAppCodebasePrincipal(uri, APP_ID, false);
-  let pm = Cc["@mozilla.org/permissionmanager;1"]
-             .getService(Ci.nsIPermissionManager);
-  pm.addFromPrincipal(_principal, MOBILEID_PERM, aAction);
-}
-
-function removePermission() {
-  let uri = Cc["@mozilla.org/network/io-service;1"]
-              .getService(Ci.nsIIOService)
-              .newURI(ORIGIN, null, null);
-  let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
-                     .getService(Ci.nsIScriptSecurityManager)
-                     .getAppCodebasePrincipal(uri, APP_ID, false);
-  let pm = Cc["@mozilla.org/permissionmanager;1"]
-             .getService(Ci.nsIPermissionManager);
-  pm.removeFromPrincipal(_principal, MOBILEID_PERM);
-}
-
-// === Mocks ===
-
-let Mock = function(aOptions) {
-  if (!aOptions) {
-    aOptions = {};
-  }
-  this._options = aOptions;
-  this._spied = {};
-};
-
-Mock.prototype = {
-  _: function(aMethod) {
-    DEBUG && do_print("_ " + aMethod + JSON.stringify(this._spied));
-    let self = this;
-    return {
-      callsLength: function(aNumberOfCalls) {
-        if (aNumberOfCalls == 0) {
-          do_check_eq(self._spied[aMethod], undefined);
-          return;
-        }
-        do_check_eq(self._spied[aMethod].length, aNumberOfCalls);
-      },
-      call: function(aCallNumber) {
-        return {
-          arg: function(aArgNumber, aValue) {
-            let _arg = self._spied[aMethod][aCallNumber - 1][aArgNumber - 1];
-            if (Array.isArray(aValue)) {
-              do_check_eq(_arg.length, aValue.length)
-              for (let i = 0; i < _arg.length; i++) {
-                do_check_eq(_arg[i], aValue[i]);
-              }
-              return;
-            }
-
-            if (typeof aValue === 'object') {
-              do_check_eq(JSON.stringify(_arg), JSON.stringify(aValue));
-              return;
-            }
-
-            do_check_eq(_arg, aValue);
-          }
-        }
-      }
-    }
-  },
-
-  _spy: function(aMethod, aArgs) {
-    DEBUG && do_print(aMethod + " - " + JSON.stringify(aArgs));
-    if (!this._spied[aMethod]) {
-      this._spied[aMethod] = [];
-    }
-    this._spied[aMethod].push(aArgs);
-  },
-
-  getSpiedCalls: function(aMethod) {
-    return this._spied[aMethod];
-  }
-};
-
-// UI Glue mock up.
-let MockUi = function(aOptions) {
-  Mock.call(this, aOptions);
-};
-
-MockUi.prototype = {
-  __proto__: Mock.prototype,
-
-  _startFlowResult: {
-    phoneNumber: PHONE_NUMBER,
-    mcc: MNC
-  },
-
-  _verifyCodePromptResult: {
-    verificationCode: VERIFICATION_CODE
-  },
-
-  startFlow: function() {
-    this._spy("startFlow", arguments);
-    return Promise.resolve(this._options.startFlowResult ||
-                           this._startFlowResult);
-  },
-
-  verificationCodePrompt: function() {
-    this._spy("verifyCodePrompt", arguments);
-    return Promise.resolve(this._options.verificationCodePromptResult ||
-                           this._verifyCodePromptResult);
-  },
-
-  verify: function() {
-    this._spy("verify", arguments);
-  },
-
-  error: function() {
-    this._spy("error", arguments);
-  },
-
-  verified: function() {
-    this._spy("verified", arguments);
-  },
-
-  set oncancel(aCallback) {
-  },
-
-  set onresendcode(aCallback) {
-  }
-};
-
 // Save original credential store instance.
 const kMobileIdentityCredStore = MobileIdentityManager.credStore;
-
-// Credentials store mock up.
-let MockCredStore = function(aOptions) {
-  Mock.call(this, aOptions);
-};
-
-MockCredStore.prototype = {
-  __proto__: Mock.prototype,
-
-  _getByOriginResult: null,
-
-  _getByMsisdnResult: null,
-
-  _getByIccIdResult: null,
-
-  getByOrigin: function() {
-    this._spy("getByOrigin", arguments);
-    let result = this._getByOriginResult;
-    if (this._options.getByOriginResult) {
-      if (Array.isArray(this._options.getByOriginResult)) {
-        result = this._options.getByOriginResult.length ?
-                 this._options.getByOriginResult.shift() : null;
-      } else {
-        result = this._options.getByOriginResult;
-      }
-    }
-    return Promise.resolve(result);
-  },
-
-  getByMsisdn: function() {
-    this._spy("getByMsisdn", arguments);
-    return Promise.resolve(this._options.getByMsisdnResult ||
-                           this._getByMsisdnResult);
-  },
-
-  getByIccId: function() {
-    this._spy("getByIccId", arguments);
-    return Promise.resolve(this._options.getByIccIdResult ||
-                           this._getByIccIdResult);
-  },
-
-  add: function() {
-    this._spy("add", arguments);
-    return Promise.resolve();
-  },
-
-  setDeviceIccIds: function() {
-    this._spy("setDeviceIccIds", arguments);
-    return Promise.resolve();
-  },
-
-  removeOrigin: function() {
-    this._spy("removeOrigin", arguments);
-    return Promise.resolve();
-  },
-
-  delete: function() {
-    this._spy("delete", arguments);
-    return Promise.resolve();
-  }
-};
-
 // Save original client instance.
 const kMobileIdentityClient = MobileIdentityManager.client;
 
-// Client mock up.
-let MockClient = function(aOptions) {
-  Mock.call(this, aOptions);
-};
-
-MockClient.prototype = {
-
-  __proto__: Mock.prototype,
-
-  _discoverResult: {
-    verificationMethods: ["sms/mt"],
-    verificationDetails: {
-      "sms/mt": {
-        mtSender: "123",
-        url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
-      }
-    }
-  },
-
-  _registerResult: {
-    msisdnSessionToken: SESSION_TOKEN
-  },
-
-  _smsMtVerifyResult: {},
-
-  _verifyCodeResult: {
-    msisdn: PHONE_NUMBER
-  },
-
-  _signResult: {
-    cert: CERTIFICATE
-  },
-
-  hawk: {
-    now: function() {
-      return Date.now();
-    }
-  },
-
-  discover: function() {
-    this._spy("discover", arguments);
-    return Promise.resolve(this._options.discoverResult ||
-                           this._discoverResult);
-  },
-
-  register: function() {
-    this._spy("register", arguments);
-    return Promise.resolve(this._options.registerResult ||
-                           this._registerResult);
-  },
-
-  smsMtVerify: function() {
-    this._spy("smsMtVerify", arguments);
-    return Promise.resolve(this._options.smsMtVerifyResult ||
-                           this._smsMtVerifyResult);
-  },
-
-  verifyCode: function() {
-    this._spy("verifyCode", arguments);
-    return Promise.resolve(this._options.verifyCodeResult ||
-                           this._verifyCodeResult);
-  },
-
-  sign: function() {
-    this._spy("sign", arguments);
-    if (this._options.signError) {
-      let error = Array.isArray(this._options.signError) ?
-                  this._options.signError.shift() :
-                  this._options.signError;
-      return Promise.reject(error);
-    }
-    return Promise.resolve(this._options.signResult || this._signResult);
-  }
-};
-
-// The test rely on having an app registered. Otherwise, it will throw.
-// Override XULAppInfo.
-const XUL_APP_INFO_UUID = Components.ID("{84fdc459-d96d-421c-9bff-a8193233ae75}");
-const XUL_APP_INFO_CONTRACT_ID = "@mozilla.org/xre/app-info;1";
-
-let (XULAppInfo = {
-  vendor: "Mozilla",
-  name: "MobileIdTest",
-  ID: "{230de50e-4cd1-11dc-8314-0800200b9a66}",
-  version: "1",
-  appBuildID: "2007010101",
-  platformVersion: "",
-  platformBuildID: "2007010101",
-  inSafeMode: false,
-  logConsoleErrors: true,
-  OS: "XPCShell",
-  XPCOMABI: "noarch-spidermonkey",
-
-  QueryInterface: XPCOMUtils.generateQI([
-    Ci.nsIXULAppInfo,
-    Ci.nsIXULRuntime,
-  ])
-}) {
-  let XULAppInfoFactory = {
-    createInstance: function (outer, iid) {
-      if (outer != null) {
-        throw Cr.NS_ERROR_NO_AGGREGATION;
-      }
-      return XULAppInfo.QueryInterface(iid);
-    }
-  };
-  Cm.QueryInterface(Ci.nsIComponentRegistrar)
-    .registerFactory(XUL_APP_INFO_UUID,
-                     "XULAppInfo",
-                     XUL_APP_INFO_CONTRACT_ID,
-                     XULAppInfoFactory);
-}
-
 // === Global cleanup ===
-
 function cleanup() {
   MobileIdentityManager.credStore = kMobileIdentityCredStore;
   MobileIdentityManager.client = kMobileIdentityClient;
   MobileIdentityManager.ui = null;
   MobileIdentityManager._iccInfo = [];
   removePermission(ORIGIN);
 }
 
 // Unregister mocks and restore original code.
 do_register_cleanup(cleanup);
-
 // === Tests ===
 function run_test() {
   run_next_test();
 }
 
 add_test(function() {
   do_print("= Initial state =");
   do_check_neq(MobileIdentityManager, undefined);
new file mode 100644
--- /dev/null
+++ b/services/mobileid/tests/xpcshell/test_mobileid_verification_flow.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Cu.import("resource://gre/modules/MobileIdentityVerificationFlow.jsm");
+
+function verifyStrategy() {
+  return Promise.resolve();
+}
+
+function cleanupStrategy() {
+}
+
+function run_test() {
+  do_print("= Bug 1101444: Invalid verification code shouldn't restart " +
+           "verification flow =");
+
+  let client = new MockClient({
+    // This will emulate two invalid attempts. The third time it will work.
+    verifyCodeError: ["INVALID", "INVALID"]
+  });
+  let ui = new MockUi();
+
+  let verificationFlow = new MobileIdentityVerificationFlow({
+    external: true,
+    sessionToken: SESSION_TOKEN,
+    msisdn: PHONE_NUMBER
+  }, ui, client, verifyStrategy, cleanupStrategy);
+
+  verificationFlow.doVerification().then(() => {
+    // We should only do the registration process once. We only try registering
+    // again when the timeout fires, but not when we enter an invalid
+    // verification code.
+    client._("register").callsLength(1);
+    client._("verifyCode").callsLength(3);
+    // Because we do two invalid attempts, we should show the invalid code error twice.
+    ui._("error").callsLength(2);
+  });
+
+  do_test_finished();
+};
--- a/services/mobileid/tests/xpcshell/xpcshell.ini
+++ b/services/mobileid/tests/xpcshell/xpcshell.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 head = head.js
 tail =
-skip-if = toolkit == 'gonk'
 
 [test_mobileid_manager.js]
+skip-if = 1
 [test_mobileid_client.js]
+[test_mobileid_verification_flow.js]