Merge m-c to inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 29 May 2015 17:00:18 -0400
changeset 246440 a89b9240f50a63fdfc66e4356f2b79f005e3973b
parent 246439 64a254d7c2eeb90a55248427cc85dd616d3bace0 (current diff)
parent 246371 45a4d6336c7326d3f7541c62b98437fd0fcb4245 (diff)
child 246441 0d29fb828423ca2665d1fdc9377f61805fa5c48b
push id28830
push usercbook@mozilla.com
push dateMon, 01 Jun 2015 13:02:44 +0000
treeherdermozilla-central@39c85ec2d644 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound. a=merge
toolkit/components/telemetry/TelemetryEnvironment.jsm
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -1,25 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 USE_RCS_MK := 1
 include $(topsrcdir)/config/makefiles/rcs.mk
 
-UA_UPDATE_FILE = ua-update.json
-
-$(UA_UPDATE_FILE): % : %.in
-	# strip out comment lines, which are not valid in JSON
-	sed -e '/^ *\/\//d' -e '/^ *$$/d' $^ > $@
-
-UA_UPDATE_FILES = $(UA_UPDATE_FILE)
-UA_UPDATE_DEST  = $(FINAL_TARGET)
-INSTALL_TARGETS += UA_UPDATE
-
 # Make sure the standalone glue doesn't try to get libxpcom.so from b2g/app.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/rules.mk
 
 APP_ICON = app
 
 ifeq ($(OS_ARCH),WINNT)
--- a/b2g/app/moz.build
+++ b/b2g/app/moz.build
@@ -76,8 +76,11 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     ]
 
 FAIL_ON_WARNINGS = True
 
 JS_PREFERENCE_FILES += [
     'b2g.js',
 ]
 
+DIST_FILES += [
+  'ua-update.json.in',
+]
--- a/b2g/app/ua-update.json.in
+++ b/b2g/app/ua-update.json.in
@@ -1,12 +1,11 @@
-// Comments must be on their own lines and must start with "//"
-
-// Send these sites a custom user-agent. Bugs to remove each override after
-// evangelism are included.
+#filter slashslash
+// Everything after the first // on a line will be removed by the preproccesor.
+// Send these sites a custom user-agent. Bugs should be included with an entry.
 {
   // bug 826347, msn.com
   "msn.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
   // bug 826353, itau.com.br
   "itau.com.br": "\\(Mobile#(Android; Mobile",
   // bug 826510, r7.com
   "r7.com": "\\(Mobile#(Android; Mobile",
   // bug 826514, estadao.com.br
--- 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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- 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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- 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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4efd19d199ae52656604f794c5a77518400220fd">
     <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="04c307a8a8439adf38c0f14d065275f571a7b486"/>
   <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- 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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- 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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "a0d4c222c1f1a8d2954539dac1537a1166aab320", 
+        "git_revision": "e6dc0f4c583407a4a52a66ce7cb11f058302a762", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "e67700d565f5f15c985a5e108622845bb23aec4b", 
+    "revision": "51be40eaad6a141d3741dbae10948968ebfc07a6", 
     "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="4efd19d199ae52656604f794c5a77518400220fd">
     <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="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="04c307a8a8439adf38c0f14d065275f571a7b486"/>
   <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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a0d4c222c1f1a8d2954539dac1537a1166aab320"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e6dc0f4c583407a4a52a66ce7cb11f058302a762"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="04c307a8a8439adf38c0f14d065275f571a7b486"/>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -2175,17 +2175,17 @@ file, You can obtain one at http://mozil
                   xbl:inherits="popupid">
                   &mixedContentBlocked2.message;
                 </xul:description>
                 <xul:description class="popup-notification-item-message"
                   xbl:inherits="popupid,mixedblockdisabled">
                   &mixedContentBlocked2.moreinfo;
                 </xul:description>
                 <xul:label anonid="mixedContent.helplink"
-                  class="text-link plain" href=""
+                  class="text-link" href=""
                   value="&mixedContentBlocked2.learnMore;"/>
               </xul:vbox>
               <xul:button
                 type="menu" label="&mixedContentBlocked2.options;"
                 sizetopopup="none">
                 <xul:menupopup>
                   <xul:menuitem anonid="mixedContentAction.unblock"
                     hidden="true" label="&mixedContentBlocked2.unblock.label;"
@@ -2213,17 +2213,17 @@ file, You can obtain one at http://mozil
                   xbl:inherits="popupid">
                   &trackingContentBlocked.message;
                 </xul:description>
                 <xul:description class="popup-notification-item-message"
                   xbl:inherits="popupid,trackingblockdisabled">
                   &trackingContentBlocked.moreinfo;
                 </xul:description>
                 <xul:label anonid="trackingContent.helplink"
-                  class="text-link plain" href=""
+                  class="text-link" href=""
                   value="&trackingContentBlocked.learnMore;"/>
               </xul:vbox>
               <xul:button
                 type="menu" label="&trackingContentBlocked.options;"
                 sizetopopup="none">
                 <xul:menupopup>
                   <xul:menuitem anonid="trackingContentAction.unblock"
                     hidden="true" label="&trackingContentBlocked.unblock2.label;"
--- a/browser/devtools/definitions.js
+++ b/browser/devtools/definitions.js
@@ -191,17 +191,17 @@ Tools.styleEditor = {
     return new StyleEditorPanel(iframeWindow, toolbox);
   }
 };
 
 Tools.shaderEditor = {
   id: "shadereditor",
   ordinal: 5,
   visibilityswitch: "devtools.shadereditor.enabled",
-  icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
+  icon: "chrome://browser/skin/devtools/tool-shadereditor.svg",
   invertIconForLightTheme: true,
   url: "chrome://browser/content/devtools/shadereditor.xul",
   label: l10n("ToolboxShaderEditor.label", shaderEditorStrings),
   panelLabel: l10n("ToolboxShaderEditor.panelLabel", shaderEditorStrings),
   tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
 
   isTargetSupported: function(target) {
     return target.hasActor("webgl") && !target.chrome;
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -728,16 +728,18 @@ MarkupView.prototype = {
       container.flashMutation();
     }
 
     this._containers.set(aNode, container);
     container.childrenDirty = true;
 
     this._updateChildren(container);
 
+    this._inspector.emit("container-created", container);
+
     return container;
   },
 
   /**
    * Mutation observer used for included nodes.
    */
   _mutationObserver: function(aMutations) {
     let requiresLayoutChange = false;
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/actor_events_form.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// This test actor is used for testing the addition of custom form data
+// on NodeActor. Custom form property is set when 'form' event is sent
+// by NodeActor actor (see 'onNodeActorForm' method).
+
+const Events = require("sdk/event/core");
+const {ActorClass, Actor, FrontClass, Front, method} =
+  require("devtools/server/protocol");
+
+const {Cu} = require("chrome");
+const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
+const {NodeActor} = devtools.require("devtools/server/actors/inspector");
+
+const EventsFormActor = ActorClass({
+  typeName: "eventsFormActor",
+
+  initialize: function() {
+    Actor.prototype.initialize.apply(this, arguments);
+  },
+
+  attach: method(function() {
+    Events.on(NodeActor, "form", this.onNodeActorForm);
+  }, {
+    request: {},
+    response: {}
+  }),
+
+  detach: method(function() {
+    Events.off(NodeActor, "form", this.onNodeActorForm);
+  }, {
+    request: {},
+    response: {}
+  }),
+
+  onNodeActorForm: function(event) {
+    let nodeActor = event.target;
+    if (nodeActor.rawNode.id == "container") {
+      let form = event.data;
+      form.setFormProperty("test-property", "test-value");
+    }
+  }
+});
+
+const EventsFormFront = FrontClass(EventsFormActor, {
+  initialize: function(client, form) {
+    Front.prototype.initialize.apply(this, arguments);
+
+    this.actorID = form[EventsFormActor.prototype.typeName];
+    this.manage(this);
+  }
+});
+
+exports.EventsFormFront = EventsFormFront;
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -1,17 +1,19 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
+  actor_events_form.js
   doc_markup_anonymous.html
   doc_markup_dragdrop.html
   doc_markup_dragdrop_autoscroll.html
   doc_markup_edit.html
   doc_markup_events.html
+  doc_markup_events_form.html
   doc_markup_events_jquery.html
   doc_markup_events-overflow.html
   doc_markup_flashing.html
   doc_markup_links.html
   doc_markup_mutation.html
   doc_markup_navigation.html
   doc_markup_not_displayed.html
   doc_markup_pagesize_01.html
@@ -44,16 +46,17 @@ skip-if = e10s # scratchpad.xul is not l
 [browser_markupview_css_completion_style_attribute.js]
 [browser_markupview_dragdrop_autoscroll.js]
 [browser_markupview_dragdrop_invalidNodes.js]
 [browser_markupview_dragdrop_isDragging.js]
 [browser_markupview_dragdrop_reorder.js]
 [browser_markupview_dragdrop_textSelection.js]
 [browser_markupview_events.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
+[browser_markupview_events_form.js]
 [browser_markupview_events-overflow.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.0.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.1.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.2.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_events_form.js
@@ -0,0 +1,62 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Testing the feature whereby custom registered actors can listen to
+// 'form' events sent by the NodeActor to hook custom data to it.
+// The test registers one backend actor providing custom form data
+// and checks that the value is properly sent to the client (NodeFront).
+
+const TEST_PAGE_URL = TEST_URL_ROOT + "doc_markup_events_form.html";
+const TEST_ACTOR_URL = CHROME_BASE + "actor_events_form.js";
+
+let {ActorRegistryFront} = devtools.require("devtools/server/actors/actor-registry");
+let {EventsFormFront} = devtools.require(TEST_ACTOR_URL);
+
+add_task(function*() {
+  info("Opening the Toolbox");
+  let {tab} = yield addTab(TEST_PAGE_URL);
+  let {toolbox} = yield openToolbox("webconsole");
+
+  info("Registering test actor");
+  let {registrar, front} = yield registerTestActor(toolbox);
+
+  info("Selecting the Inspector panel");
+  let inspector = yield toolbox.selectTool("inspector");
+  let container = yield getContainerForSelector("#container", inspector);
+  isnot(container, null, "There must be requested container");
+
+  let nodeFront = container.node;
+  let value = nodeFront.getFormProperty("test-property");
+  is(value, "test-value", "There must be custom property");
+
+  info("Unregistering actor");
+  yield unregisterActor(registrar, front);
+});
+
+function registerTestActor(toolbox) {
+  let deferred = promise.defer();
+
+  let options = {
+    prefix: "eventsFormActor",
+    actorClass: "EventsFormActor",
+    moduleUrl: TEST_ACTOR_URL,
+  };
+
+  // Register as a tab actor
+  let client = toolbox.target.client;
+  registerTabActor(client, options).then(({registrar, form}) => {
+    // Attach to the registered actor
+    let front = EventsFormFront(client, form);
+    front.attach().then(() => {
+      deferred.resolve({
+        front: front,
+        registrar: registrar,
+      });
+    });
+  });
+
+  return deferred.promise;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/doc_markup_events_form.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <style>
+    </style>
+  </head>
+  <body>
+    <div id="container">
+  </body>
+</html>
--- a/browser/devtools/markupview/test/head.js
+++ b/browser/devtools/markupview/test/head.js
@@ -5,16 +5,18 @@
 const Cu = Components.utils;
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 let promise = devtools.require("resource://gre/modules/Promise.jsm").Promise;
 let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
 let clipboard = devtools.require("sdk/clipboard");
 let {setTimeout, clearTimeout} = devtools.require("sdk/timers");
+let {promiseInvoke} = devtools.require("devtools/async-utils");
+
 
 // All test are asynchronous
 waitForExplicitFinish();
 
 // If a test times out we want to see the complete log and not just the last few
 // lines.
 SimpleTest.requestCompleteLog();
 
@@ -103,34 +105,46 @@ function loadHelperScript(filePath) {
 function reloadPage(inspector) {
   info("Reloading the page");
   let newRoot = inspector.once("new-root");
   content.location.reload();
   return newRoot;
 }
 
 /**
+ * Open the toolbox, with given tool visible.
+ * @param {string} toolId ID of the tool that should be visible by default.
+ * @return a promise that resolves when the tool is ready.
+ */
+function openToolbox(toolId) {
+  info("Opening the inspector panel");
+  let deferred = promise.defer();
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  gDevTools.showToolbox(target, toolId).then(function(toolbox) {
+    info("The toolbox is open");
+    deferred.resolve({toolbox: toolbox});
+  }).then(null, console.error);
+
+  return deferred.promise;
+}
+
+/**
  * Open the toolbox, with the inspector tool visible.
  * @return a promise that resolves when the inspector is ready
  */
 function openInspector() {
-  info("Opening the inspector panel");
-  let def = promise.defer();
-
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    info("The toolbox is open");
+  return openToolbox("inspector").then(({toolbox}) => {
     let inspector = toolbox.getCurrentPanel();
-    inspector.once("inspector-updated", () => {
+    let eventId = "inspector-updated";
+    return inspector.once("inspector-updated").then(() => {
       info("The inspector panel is active and ready");
-      def.resolve({toolbox: toolbox, inspector: inspector});
+      return {toolbox: toolbox, inspector: inspector};
     });
-  }).then(null, console.error);
-
-  return def.promise;
+  });
 }
 
 /**
  * Wait for a content -> chrome message on the message manager (the window
  * messagemanager is used).
  * @param {String} name The message name
  * @return {Promise} A promise that resolves to the response data when the
  * message has been received
@@ -694,8 +708,69 @@ function contextMenuClick(element) {
   let button = 2;  // right click
 
   evt.initMouseEvent('contextmenu', true, true,
        element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false,
        false, false, false, button, null);
 
   element.dispatchEvent(evt);
 }
+
+/**
+ * Registers new backend tab actor.
+ *
+ * @param {DebuggerClient} client RDP client object (toolbox.target.client)
+ * @param {Object} options Configuration object with the following options:
+ *
+ * - moduleUrl {String}: URL of the module that contains actor implementation.
+ * - prefix {String}: prefix of the actor.
+ * - actorClass {ActorClass}: Constructor object for the actor.
+ * - frontClass {FrontClass}: Constructor object for the front part
+ * of the registered actor.
+ *
+ * @returns {Promise} A promise that is resolved when the actor is registered.
+ * The resolved value has two properties:
+ *
+ * - registrar {ActorActor}: A handle to the registered actor that allows
+ * unregistration.
+ * - form {Object}: The JSON actor form provided by the server.
+ */
+function registerTabActor(client, options) {
+  let moduleUrl = options.moduleUrl;
+
+  // Since client.listTabs doesn't use promises we need to
+  // 'promisify' it using 'promiseInvoke' helper method.
+  // This helps us to chain all promises and catch errors.
+  return promiseInvoke(client, client.listTabs).then(response => {
+    let config = {
+      prefix: options.prefix,
+      constructor: options.actorClass,
+      type: { tab: true },
+    };
+
+    // Register the custom actor on the backend.
+    let registry = ActorRegistryFront(client, response);
+    return registry.registerActor(moduleUrl, config).then(registrar => {
+      return client.getTab().then(response => {
+        return {
+          registrar: registrar,
+          form: response.tab
+        };
+      });
+    });
+  });
+}
+
+/**
+ * A helper for unregistering an existing backend actor.
+ *
+ * @param {ActorActor} registrar A handle to the registered actor
+ * that has been received after registration.
+ * @param {Front} Corresponding front object.
+ *
+ * @returns A promise that is resolved when the unregistration
+ * has finished.
+ */
+function unregisterActor(registrar, front) {
+  return front.detach().then(() => {
+    return registrar.unregister();
+  });
+}
--- a/browser/devtools/performance/modules/logic/waterfall-utils.js
+++ b/browser/devtools/performance/modules/logic/waterfall-utils.js
@@ -13,40 +13,55 @@ loader.lazyRequireGetter(this, "TIMELINE
 /**
  * Collapses markers into a tree-like structure. Currently, this only goes
  * one level deep.
  * @param object markerNode
  * @param array markersList
  */
 function collapseMarkersIntoNode({ markerNode, markersList }) {
   let [getOrCreateParentNode, getCurrentParentNode, clearParentNode] = makeParentNodeFactory();
+  let uid = 0;
 
   for (let i = 0, len = markersList.length; i < len; i++) {
     let curr = markersList[i];
-    let blueprint = TIMELINE_BLUEPRINT[curr.name];
+
+    // Make sure all the markers have an assigned number id. This makes it
+    // easier to find them in a waterfall, for example.
+    curr.uid = ++uid;
 
     let parentNode = getCurrentParentNode();
+    let blueprint = TIMELINE_BLUEPRINT[curr.name];
     let collapse = blueprint.collapseFunc || (() => null);
     let peek = distance => markersList[i + distance];
     let collapseInfo = collapse(parentNode, curr, peek);
 
     if (collapseInfo) {
       let { toParent, withData, forceNew, forceEnd } = collapseInfo;
 
       // If the `forceNew` prop is set on the collapse info, then a new parent
       // marker needs to be created even if there is one already available.
       if (forceNew) {
         clearParentNode();
       }
       // If the `toParent` prop is set on the collapse info, then this marker
       // can be collapsed into a higher-level parent marker.
       if (toParent) {
-        let parentNode = getOrCreateParentNode(markerNode, toParent, curr.start);
-        parentNode.end = curr.end;
+        let parentNode = getOrCreateParentNode({
+          uid: ++uid,
+          owner: markerNode,
+          name: toParent,
+          start: curr.start,
+          end: curr.end
+        });
+
+        // A parent marker, even when created, will always have at least one
+        // child submarker (the one which caused it to be created).
         parentNode.submarkers.push(curr);
+
+        // Optionally, additional data may be stapled on this parent marker.
         for (let key in withData) {
           parentNode[key] = withData[key];
         }
       }
       // If the `forceEnd` prop is set on the collapse info, then the higher-level
       // parent marker is full and should be finalized.
       if (forceEnd) {
         clearParentNode();
@@ -57,23 +72,25 @@ function collapseMarkersIntoNode({ marke
     }
   }
 }
 
 /**
  * Creates an empty parent marker, which functions like a regular marker,
  * but is able to hold additional child markers.
  * @param string name
+ * @param number uid
  * @param number start [optional]
  * @param number end [optional]
  * @return object
  */
-function makeEmptyMarkerNode(name, start, end) {
+function makeEmptyMarkerNode(name, uid, start, end) {
   return {
     name: name,
+    uid: uid,
     start: start,
     end: end,
     submarkers: []
   };
 }
 
 /**
  * Creates a factory for markers containing other markers.
@@ -84,23 +101,25 @@ function makeParentNodeFactory() {
 
   return [
     /**
      * Gets the current parent marker for the given marker name. If it doesn't
      * exist, it creates it and appends it to another parent marker.
      * @param object owner
      * @param string name
      * @param number start
+     * @param number end
      * @return object
      */
-    function getOrCreateParentNode(owner, name, start) {
+    function getOrCreateParentNode({ owner, name, uid, start, end }) {
       if (marker && marker.name == name) {
+        marker.end = end;
         return marker;
       } else {
-        marker = makeEmptyMarkerNode(name, start);
+        marker = makeEmptyMarkerNode(name, uid, start, end);
         owner.submarkers.push(marker);
         return marker;
       }
     },
 
     /**
      * Gets the current marker marker.
      * @return object
--- a/browser/devtools/performance/modules/widgets/marker-details.js
+++ b/browser/devtools/performance/modules/widgets/marker-details.js
@@ -45,16 +45,24 @@ MarkerDetails.prototype = {
    * Sets this view's width.
    * @param boolean
    */
   set width(value) {
     this._parent.setAttribute("width", value);
   },
 
   /**
+   * Sets this view's visibility.
+   * @param boolean
+   */
+  set hidden(value) {
+    this._parent.hidden = value;
+  },
+
+  /**
    * Clears the marker details from this view.
    */
   empty: function() {
     this._parent.innerHTML = "";
   },
 
   /**
    * Populates view with marker's details.
--- a/browser/devtools/performance/modules/widgets/marker-view.js
+++ b/browser/devtools/performance/modules/widgets/marker-view.js
@@ -169,22 +169,17 @@ MarkerView.prototype = Heritage.extend(A
 
   /**
    * Builds all the nodes representing a marker in the waterfall.
    * @param nsIDOMNode document
    * @param nsIDOMNode targetNode
    * @param nsIDOMNode arrowNode
    */
   _buildMarkerCells: function(doc, targetNode, arrowNode) {
-    // Root markers are an implementation detail and shouldn't be shown.
     let marker = this.marker;
-    if (marker.name == "(root)") {
-      return;
-    }
-
     let style = this.root._blueprint[marker.name];
     let startTime = this.root._interval.startTime;
     let endTime = this.root._interval.endTime;
 
     let sidebarCell = this._buildMarkerSidebar(
       doc, style, marker);
 
     let timebarCell = this._buildMarkerTimebar(
--- a/browser/devtools/performance/test/browser_perf-overview-render-03.js
+++ b/browser/devtools/performance/test/browser_perf-overview-render-03.js
@@ -1,15 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that the overview graphs share the exact same width and scaling.
  */
 function* spawnTest() {
+  // This test seems to take a long time to cleanup on Ubuntu VMs.
+  requestLongerTimeout(2);
+
   let { panel } = yield initPerformance(SIMPLE_URL);
   let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
 
   // Enable memory to test all the overview graphs.
   Services.prefs.setBoolPref(MEMORY_PREF, true);
 
   yield startRecording(panel);
 
--- a/browser/devtools/performance/test/browser_timeline-waterfall-rerender.js
+++ b/browser/devtools/performance/test/browser_timeline-waterfall-rerender.js
@@ -26,35 +26,43 @@ function* spawnTest() {
   let initialBarsCount = $$(".waterfall-marker-bar").length;
 
   // Select a portion of the overview.
   let timeline = OverviewView.graphs.get("timeline");
   let rerendered = WaterfallView.once(EVENTS.WATERFALL_RENDERED);
   timeline.setSelection({ start: 0, end: timeline.width / 2 })
   yield rerendered;
 
+  ok(!$(".waterfall-tree-item:focus"),
+    "There is no item focused in the waterfall yet.");
+  ok($("#waterfall-details").hidden,
+    "The waterfall sidebar is initially hidden.");
+
   // Focus the second item in the tree.
   WaterfallView._markersRoot.getChild(1).focus();
 
   let beforeResizeBarsCount = $$(".waterfall-marker-bar").length;
   ok(beforeResizeBarsCount < initialBarsCount,
     "A subset of the total markers was selected.");
 
   is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
     "The correct item was focused in the tree.");
+  ok(!$("#waterfall-details").hidden,
+    "The waterfall sidebar is now visible.");
 
   rerendered = WaterfallView.once(EVENTS.WATERFALL_RENDERED);
   EventUtils.sendMouseEvent({ type: "mouseup" }, WaterfallView.detailsSplitter);
   yield rerendered;
 
   let afterResizeBarsCount = $$(".waterfall-marker-bar").length;
   is(afterResizeBarsCount, beforeResizeBarsCount,
     "The same subset of the total markers remained visible.");
 
   // Temporarily disable the following assertion; intermittent failures.
   // Bug 1169352.
-
   // is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
   //   "The correct item is still focused in the tree.");
+  ok(!$("#waterfall-details").hidden,
+    "The waterfall sidebar is still visible.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/performance/test/browser_waterfall-collapse.js
+++ b/browser/devtools/performance/test/browser_waterfall-collapse.js
@@ -164,195 +164,229 @@ const gTestMarkers = [
   start: 45,
   end: 46,
   name: "GarbageCollection"
 }
 ];
 
 const gExpectedOutput = {
   name: "(root)",
+  uid: (void 0),
   start: (void 0),
   end: (void 0),
   submarkers: [{
     name: "Styles",
+    uid: 2,
     start: 1,
     end: 4,
     submarkers: [{
       start: 1,
       end: 2,
-      name: "Styles"
+      name: "Styles",
+      uid: 1
     }, {
       start: 3,
       end: 4,
-      name: "Styles"
+      name: "Styles",
+      uid: 3
     }]
   }, {
     name: "Reflow",
+    uid: 6,
     start: 5,
     end: 8,
     submarkers: [{
       start: 5,
       end: 6,
-      name: "Reflow"
+      name: "Reflow",
+      uid: 5
     }, {
       start: 7,
       end: 8,
-      name: "Reflow"
+      name: "Reflow",
+      uid: 7
     }]
   }, {
     name: "Paint",
+    uid: 10,
     start: 9,
     end: 12,
     submarkers: [{
       start: 9,
       end: 10,
-      name: "Paint"
+      name: "Paint",
+      uid: 9
     }, {
       start: 11,
       end: 12,
-      name: "Paint"
+      name: "Paint",
+      uid: 11
     }]
   }, {
     start: 13,
     end: 14,
     name: "DOMEvent",
     eventPhase: 1,
-    type: "foo1"
+    type: "foo1",
+    uid: 13
   }, {
     start: 15,
     end: 16,
-    name: "TimeStamp"
+    name: "TimeStamp",
+    uid: 14
   }, {
     name: "meta::DOMEvent+JS",
+    uid: 16,
     start: 17,
     end: 20,
     submarkers: [{
       start: 17,
       end: 18,
       name: "DOMEvent",
       eventPhase: 2,
-      type: "foo2"
+      type: "foo2",
+      uid: 15
     }, {
       start: 19,
       end: 20,
       name: "Javascript",
       stack: 1,
-      endStack: 2
+      endStack: 2,
+      uid: 17
     }],
     type: "foo2",
     eventPhase: 2,
     stack: 1,
     endStack: 2
   }, {
     name: "meta::DOMEvent+JS",
+    uid: 20,
     start: 21,
     end: 24,
     submarkers: [{
       start: 21,
       end: 22,
       name: "DOMEvent",
       eventPhase: 3,
-      type: "foo3"
+      type: "foo3",
+      uid: 19
     }, {
       start: 23,
       end: 24,
       name: "Javascript",
       stack: 3,
-      endStack: 4
+      endStack: 4,
+      uid: 21
     }],
     type: "foo3",
     eventPhase: 3,
     stack: 3,
     endStack: 4
   }, {
     name: "meta::DOMEvent+JS",
+    uid: 24,
     start: 25,
     end: 28,
     submarkers: [{
       start: 25,
       end: 26,
       name: "DOMEvent",
       eventPhase: 4,
-      type: "foo4"
+      type: "foo4",
+      uid: 23
     }, {
       start: 27,
       end: 28,
       name: "Javascript",
       stack: 5,
-      endStack: 6
+      endStack: 6,
+      uid: 25
     }],
     type: "foo4",
     eventPhase: 4,
     stack: 5,
     endStack: 6
   }, {
     name: "Javascript",
+    uid: 28,
     start: 29,
     end: 32,
     submarkers: [{
       start: 29,
       end: 30,
       name: "Javascript",
       stack: 7,
-      endStack: 8
+      endStack: 8,
+      uid: 27
     }, {
       start: 31,
       end: 32,
       name: "Javascript",
       stack: 9,
-      endStack: 10
+      endStack: 10,
+      uid: 29
     }]
   }, {
     start: 33,
     end: 34,
     name: "DOMEvent",
     eventPhase: 5,
-    type: "foo5"
+    type: "foo5",
+    uid: 31
   }, {
     start: 35,
     end: 36,
     name: "DOMEvent",
     eventPhase: 6,
-    type: "foo6"
+    type: "foo6",
+    uid: 32
   }, {
     name: "meta::DOMEvent+JS",
+    uid: 34,
     start: 37,
     end: 40,
     submarkers: [{
       start: 37,
       end: 38,
       name: "DOMEvent",
       eventPhase: 7,
-      type: "foo6"
+      type: "foo6",
+      uid: 33
     }, {
       start: 39,
       end: 40,
       name: "Javascript",
       stack: 11,
-      endStack: 12
+      endStack: 12,
+      uid: 35
     }],
     type: "foo6",
     eventPhase: 7,
     stack: 11,
     endStack: 12
   }, {
     name: "Javascript",
+    uid: 38,
     start: 41,
     end: 44,
     submarkers: [{
       start: 41,
       end: 42,
       name: "Javascript",
       stack: 13,
-      endStack: 14
+      endStack: 14,
+      uid: 37
     }, {
       start: 43,
       end: 44,
       name: "Javascript",
       stack: 15,
-      endStack: 16
+      endStack: 16,
+      uid: 39
     }]
   }, {
     start: 45,
     end: 46,
-    name: "GarbageCollection"
+    name: "GarbageCollection",
+    uid: 41
   }]
 };
+
--- a/browser/devtools/performance/views/details-waterfall.js
+++ b/browser/devtools/performance/views/details-waterfall.js
@@ -22,40 +22,46 @@ let WaterfallView = Heritage.extend(Deta
   rangeChangeDebounceTime: 75, // ms
 
   /**
    * Sets up the view with event binding.
    */
   initialize: function () {
     DetailsSubview.initialize.call(this);
 
+    this._cache = new WeakMap();
+
     this._onMarkerSelected = this._onMarkerSelected.bind(this);
     this._onResize = this._onResize.bind(this);
     this._onViewSource = this._onViewSource.bind(this);
 
     this.headerContainer = $("#waterfall-header");
     this.breakdownContainer = $("#waterfall-breakdown");
     this.detailsContainer = $("#waterfall-details");
     this.detailsSplitter = $("#waterfall-view > splitter");
 
     this.details = new MarkerDetails($("#waterfall-details"), $("#waterfall-view > splitter"));
+    this.details.hidden = true;
+
     this.details.on("resize", this._onResize);
     this.details.on("view-source", this._onViewSource);
     window.addEventListener("resize", this._onResize);
 
     // TODO bug 1167093 save the previously set width, and ensure minimum width
     this.details.width = MARKER_DETAILS_WIDTH;
   },
 
   /**
    * Unbinds events.
    */
   destroy: function () {
     DetailsSubview.destroy.call(this);
 
+    this._cache = null;
+
     this.details.off("resize", this._onResize);
     this.details.off("view-source", this._onViewSource);
     window.removeEventListener("resize", this._onResize);
   },
 
   /**
    * Method for handling all the set up for rendering a new waterfall.
    *
@@ -78,21 +84,21 @@ let WaterfallView = Heritage.extend(Deta
    * updating the markers detail view.
    */
   _onMarkerSelected: function (event, marker) {
     let recording = PerformanceController.getCurrentRecording();
     let frames = recording.getFrames();
 
     if (event === "selected") {
       this.details.render({ toolbox: gToolbox, marker, frames });
-      this._selected = marker;
+      this.details.hidden = false;
+      this._lastSelected = marker.uid;
     }
     if (event === "unselected") {
       this.details.empty();
-      this._selected = null;
     }
   },
 
   /**
    * Called when the marker details view is resized.
    */
   _onResize: function () {
     setNamedTimeout("waterfall-resize", WATERFALL_RESIZE_EVENTS_DRAIN, () => {
@@ -116,23 +122,29 @@ let WaterfallView = Heritage.extend(Deta
     gToolbox.viewSourceInDebugger(file, line);
   },
 
   /**
    * Called when the recording is stopped and prepares data to
    * populate the waterfall tree.
    */
   _prepareWaterfallTree: function(markers) {
+    let cached = this._cache.get(markers);
+    if (cached) {
+      return cached;
+    }
+
     let rootMarkerNode = WaterfallUtils.makeEmptyMarkerNode("(root)");
 
     WaterfallUtils.collapseMarkersIntoNode({
       markerNode: rootMarkerNode,
       markersList: markers
     });
 
+    this._cache.set(markers, rootMarkerNode);
     return rootMarkerNode;
   },
 
   /**
    * Renders the waterfall tree.
    */
   _populateWaterfallTree: function(rootMarkerNode, interval) {
     let root = new MarkerView({
@@ -157,18 +169,18 @@ let WaterfallView = Heritage.extend(Deta
     this.breakdownContainer.innerHTML = "";
     root.attachTo(this.breakdownContainer);
 
     this.headerContainer.innerHTML = "";
     header.attachTo(this.headerContainer);
 
     // If an item was previously selected in this view, attempt to
     // re-select it by traversing the newly created tree.
-    if (this._selected) {
-      let item = root.find(i => i.marker == this._selected);
+    if (this._lastSelected) {
+      let item = root.find(i => i.marker.uid == this._lastSelected);
       if (item) {
         item.focus();
       }
     }
   },
 
   toString: () => "[object WaterfallView]"
 });
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -158,16 +158,22 @@ var Scratchpad = {
     }
   },
 
   /**
    * Add the event event listeners for command events.
    */
   _setupCommandListeners: function SP_setupCommands() {
     let commands = {
+      "cmd_find": () => {
+        goDoCommand('cmd_find');
+      },
+      "cmd_findAgain": () => {
+        goDoCommand('cmd_findAgain');
+      },
       "cmd_gotoLine": () => {
         goDoCommand('cmd_gotoLine');
       },
       "sp-cmd-newWindow": () => {
         Scratchpad.openScratchpad();
       },
       "sp-cmd-openFile": () => {
         Scratchpad.openFile();
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -31,16 +31,18 @@
 <script type="application/javascript;version=1.8"
         src="chrome://browser/content/devtools/theme-switching.js"/>
 <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
 <script type="application/javascript" src="chrome://browser/content/devtools/scratchpad.js"/>
 
 <commandset id="editMenuCommands"/>
 
 <commandset id="sourceEditorCommands">
+  <command id="cmd_find" oncommand=";"/>
+  <command id="cmd_findAgain" oncommand=";"/>
   <command id="cmd_gotoLine" oncommand=";"/>
 </commandset>
 
 <commandset id="sp-commandset">
   <command id="sp-cmd-newWindow" oncommand=";"/>
   <command id="sp-cmd-openFile" oncommand=";"/>
   <command id="sp-cmd-clearRecentFiles" oncommand=";"/>
   <command id="sp-cmd-save" oncommand=";"/>
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1914,20 +1914,16 @@ toolbarbutton.chevron > .toolbarbutton-i
   text-shadow: none;
   background-image: linear-gradient(#B4211B, #8A1915);
   border-radius: 1px;
   -moz-margin-end: 2px;
 }
 
 /* Social toolbar item */
 
-#social-undoactivation-button {
-  -moz-margin-start: 0; /* override default label margin to match description margin */
-}
-
 .social-activation-icon {
   width: auto;
   height: auto;
   max-height: 64px;
   max-width: 64px;
 }
 
 #social-activation-message {
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -382,16 +382,17 @@ browser.jar:
   skin/classic/browser/devtools/profiler-stopwatch.svg      (../shared/devtools/images/profiler-stopwatch.svg)
   skin/classic/browser/devtools/profiler-stopwatch-checked.svg      (../shared/devtools/images/profiler-stopwatch-checked.svg)
   skin/classic/browser/devtools/tool-options.svg            (../shared/devtools/images/tool-options.svg)
   skin/classic/browser/devtools/tool-webconsole.svg         (../shared/devtools/images/tool-webconsole.svg)
   skin/classic/browser/devtools/tool-debugger.svg           (../shared/devtools/images/tool-debugger.svg)
   skin/classic/browser/devtools/tool-debugger-paused.svg    (../shared/devtools/images/tool-debugger-paused.svg)
   skin/classic/browser/devtools/tool-inspector.svg          (../shared/devtools/images/tool-inspector.svg)
   skin/classic/browser/devtools/tool-inspector.svg          (../shared/devtools/images/tool-inspector.svg)
+  skin/classic/browser/devtools/tool-shadereditor.svg       (../shared/devtools/images/tool-shadereditor.svg)
   skin/classic/browser/devtools/tool-styleeditor.svg        (../shared/devtools/images/tool-styleeditor.svg)
   skin/classic/browser/devtools/tool-storage.svg            (../shared/devtools/images/tool-storage.svg)
   skin/classic/browser/devtools/tool-profiler.svg           (../shared/devtools/images/tool-profiler.svg)
   skin/classic/browser/devtools/tool-profiler-active.svg    (../shared/devtools/images/tool-profiler-active.svg)
   skin/classic/browser/devtools/tool-network.svg            (../shared/devtools/images/tool-network.svg)
   skin/classic/browser/devtools/tool-scratchpad.svg         (../shared/devtools/images/tool-scratchpad.svg)
   skin/classic/browser/devtools/tool-webaudio.svg           (../shared/devtools/images/tool-webaudio.svg)
   skin/classic/browser/devtools/close.png                   (../shared/devtools/images/close.png)
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3143,20 +3143,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 
   #identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
     -moz-image-region: rect(128px, 128px, 256px, 0px);
   }
 
   #identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
     -moz-image-region: rect(256px, 128px, 384px, 0px);
   }
-
-  #identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
-    list-style-image: url("chrome://branding/content/icon128.png");
-  }
 }
 
 /* Popup Body Text */
 .identity-popup-description {
   white-space: pre-wrap;
   -moz-padding-start: 15px;
   margin: 2px 0 4px;
 }
@@ -3426,30 +3422,18 @@ notification[value="loop-sharing-notific
 }
 
 .popup-notification-body[popupid="addon-progress"],
 .popup-notification-body[popupid="addon-install-confirmation"] {
   width: 28em;
   max-width: 28em;
 }
 
-#addon-progress-notification-progresstext,
-#addon-progress-notification-progressmeter {
-  /* override default label margin to match description margin */
-  -moz-margin-start: 0;
-  -moz-margin-end: 0;
-}
-
 .addon-install-confirmation-name {
   font-weight: bold;
-  -moz-margin-start: 0 !important; /* override default label margin to match description margin */
-}
-
-#pointerLock-cancel {
-  margin: 0px;
 }
 
 /* Popup Buttons */
 #identity-popup-more-info-button {
   @hudButton@
   margin: 10px 0 0;
   min-height: 0px;
 }
@@ -3663,20 +3647,16 @@ notification[value="loop-sharing-notific
 #developer-toolbar-toolbox-button[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
   background-image: linear-gradient(#B4211B, #8A1915);
   border-radius: 1px;
 }
 
-#social-undoactivation-button {
-  -moz-margin-start: 0; /* override default label margin to match description margin */
-}
-
 .social-activation-icon {
   width: auto;
   height: auto;
   max-height: 64px;
   max-width: 64px;
 }
 
 #social-activation-message {
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -498,16 +498,17 @@ browser.jar:
   skin/classic/browser/devtools/profiler-stopwatch.svg      (../shared/devtools/images/profiler-stopwatch.svg)
   skin/classic/browser/devtools/profiler-stopwatch-checked.svg      (../shared/devtools/images/profiler-stopwatch-checked.svg)
   skin/classic/browser/devtools/tool-options.svg            (../shared/devtools/images/tool-options.svg)
   skin/classic/browser/devtools/tool-webconsole.svg         (../shared/devtools/images/tool-webconsole.svg)
   skin/classic/browser/devtools/tool-debugger.svg           (../shared/devtools/images/tool-debugger.svg)
   skin/classic/browser/devtools/tool-debugger-paused.svg    (../shared/devtools/images/tool-debugger-paused.svg)
   skin/classic/browser/devtools/tool-inspector.svg          (../shared/devtools/images/tool-inspector.svg)
   skin/classic/browser/devtools/tool-inspector.svg          (../shared/devtools/images/tool-inspector.svg)
+  skin/classic/browser/devtools/tool-shadereditor.svg       (../shared/devtools/images/tool-shadereditor.svg)
   skin/classic/browser/devtools/tool-styleeditor.svg        (../shared/devtools/images/tool-styleeditor.svg)
   skin/classic/browser/devtools/tool-storage.svg            (../shared/devtools/images/tool-storage.svg)
   skin/classic/browser/devtools/tool-profiler.svg           (../shared/devtools/images/tool-profiler.svg)
   skin/classic/browser/devtools/tool-profiler-active.svg    (../shared/devtools/images/tool-profiler-active.svg)
   skin/classic/browser/devtools/tool-network.svg            (../shared/devtools/images/tool-network.svg)
   skin/classic/browser/devtools/tool-scratchpad.svg         (../shared/devtools/images/tool-scratchpad.svg)
   skin/classic/browser/devtools/tool-webaudio.svg           (../shared/devtools/images/tool-webaudio.svg)
   skin/classic/browser/devtools/close.png                   (../shared/devtools/images/close.png)
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/devtools/images/tool-shadereditor.svg
@@ -0,0 +1,26 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <rect x="2" y="2" width="12" height="12" fill="#edf0f1" fill-opacity=".1"/>
+  <polygon points="2,2 14,14 2,14" fill="#edf0f1" fill-opacity=".35"/>
+  <rect x="2.5" y="2.5" width="11" height="11" fill="none" stroke="#edf0f1" stroke-width="1"/>
+  <g fill="#edf0f1" fill-opacity=".65">
+    <polygon points="3,3 5,3 5,5"/>
+    <rect x="11" y="3" width="2" height="2"/>
+    <rect x="7" y="3" width="2" height="2"/>
+    <polygon points="5,5 7,5 7,7"/>
+    <rect x="9" y="5" width="2" height="2"/>
+    <polygon points="7,7 9,7 9,9"/>
+    <rect x="11" y="7" width="2" height="2"/>
+    <polygon points="9,9 11,9 11,11"/>
+    <polygon points="11,11 13,11 13,13"/>
+  </g>
+  <line x1="3" y1="3" x2="13" y2="13" stroke="#edf0f1" stroke-width="1"/>
+  <g fill="#edf0f1">
+    <circle cx="2" cy="2" r="1"/>
+    <circle cx="14" cy="2" r="1"/>
+    <circle cx="2" cy="14" r="1"/>
+    <circle cx="14" cy="14" r="1"/>
+  </g>
+</svg>
--- a/browser/themes/shared/identity-block.inc.css
+++ b/browser/themes/shared/identity-block.inc.css
@@ -154,9 +154,14 @@
   #identity-box:hover > #page-proxy-favicon {
     -moz-image-region: rect(0, 64px, 32px, 32px);
   }
 
   #identity-box:hover:active > #page-proxy-favicon,
   #identity-box[open=true] > #page-proxy-favicon {
     -moz-image-region: rect(0, 96px, 32px, 64px);
   }
+
+  #identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
+    list-style-image: url("chrome://branding/content/icon128.png");
+    -moz-image-region: rect(0, 128px, 128px, 0);
+  }
 }
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -237,18 +237,18 @@ description > html|a {
   margin: 0;
 }
 
 #weavePrefsDeck > vbox > label,
 #weavePrefsDeck > vbox > groupbox,
 #weavePrefsDeck > vbox > description,
 #weavePrefsDeck > vbox > #pairDevice > label,
 #weavePrefsDeck > #needsUpdate > hbox > #loginError,
-#weavePrefsDeck > #hasFxaAccount > hbox:not(#tosPP-normal) > label,
-#weavePrefsDeck > #hasFxaAccount > hbox:not(#tosPP-small) > label {
+#weavePrefsDeck > #hasFxaAccount > vbox > label,
+#weavePrefsDeck > #hasFxaAccount > hbox:not(#tosPP-normal) > label {
   /* no margin-start for elements at the begin of a line */
   -moz-margin-start: 0;
 }
 
 #tabsElement {
   -moz-margin-end: 4px; /* add the 4px end-margin of other elements */
 }
 
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2561,20 +2561,16 @@ notification[value="loop-sharing-notific
   text-shadow: none;
   background-image: linear-gradient(#B4211B, #8A1915);
   border-radius: 1px;
   -moz-margin-end: 5px;
 }
 
 /* Social toolbar item */
 
-#social-undoactivation-button {
-  -moz-margin-start: 0; /* override default label margin to match description margin */
-}
-
 #socialActivatedNotification .popup-notification-button-container {
   margin-left: 6px;
 }
 
 .social-activation-icon {
   width: auto;
   height: auto;
   max-height: 64px;
--- a/browser/themes/windows/downloads/indicator.css
+++ b/browser/themes/windows/downloads/indicator.css
@@ -14,34 +14,51 @@
      This is required by the animated event notification. */
   position: relative;
   /* The selected tab may overlap #downloads-indicator-notification */
   z-index: 5;
 }
 
 /*** Main indicator icon ***/
 
+@media not all and (min-resolution: 1.1dppx) {
+  #downloads-indicator-icon {
+    --downloads-indicator-icon: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 0, 198, 18, 180);
+    --downloads-indicator-icon-attention: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 18, 198, 36, 180);
+    --downloads-indicator-icon-inverted: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 198, 18, 180);
+    --downloads-indicator-icon-attention-inverted: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 18, 198, 36, 180);
+  }
+}
+
+@media (min-resolution: 1.1dppx) {
+  #downloads-indicator-icon {
+    --downloads-indicator-icon: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 396, 36, 360);
+    --downloads-indicator-icon-attention: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 36, 396, 72, 360);
+    --downloads-indicator-icon-inverted: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted@2x.png"), 0, 396, 36, 360);
+    --downloads-indicator-icon-attention-inverted: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted@2x.png"), 36, 396, 72, 360);
+  }
+}
+
 #downloads-indicator-icon {
-  background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
-                              0, 198, 18, 180) center no-repeat;
-  min-width: 18px;
-  min-height: 18px;
+  background: var(--downloads-indicator-icon) center no-repeat;
+  width: 18px;
+  height: 18px;
+  background-size: 18px;
 }
 
 toolbar[brighttext] #downloads-button:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon {
-  background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
-                              0, 198, 18, 180) center no-repeat;
+  background-image: var(--downloads-indicator-icon-inverted);
 }
 
 #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
-  background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 18, 198, 36, 180);
+  background-image: var(--downloads-indicator-icon-attention);
 }
 
 toolbar[brighttext] #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
-  background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 18, 198, 36, 180);
+  background-image: var(--downloads-indicator-icon-attention-inverted);
 }
 
 #downloads-button[cui-areatype="menu-panel"][attention] {
   list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel.png");
   -moz-image-region: auto;
 }
 
 %ifdef WINDOWS_AERO
@@ -54,31 +71,30 @@ toolbar[brighttext] #downloads-button[at
 %ifdef WINDOWS_AERO
 }
 %endif
 
 /* In the next few rules, we use :not([counter]) as a shortcut that is
    equivalent to -moz-any([progress], [paused]). */
 
 #downloads-button:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
-  background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
-                              0, 198, 18, 180) center no-repeat;
+  background: var(--downloads-indicator-icon) center no-repeat;
   background-size: 12px;
 }
 
 toolbar[brighttext] #downloads-button:not([counter]):not([attention]) > #downloads-indicator-anchor > #downloads-button-progress-area > #downloads-indicator-counter {
-  background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 198, 18, 180);
+  background-image: var(--downloads-indicator-icon-inverted);
 }
 
 #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
-  background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 18, 198, 36, 180);
+  background-image: var(--downloads-indicator-icon-attention);
 }
 
 toolbar[brighttext] #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
-  background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 18, 198, 36, 180);
+  background-image: var(--downloads-indicator-icon-attention-inverted);
 }
 
 /*** Download notifications ***/
 
 #downloads-indicator-notification {
   opacity: 0;
   background-size: 16px;
   background-position: center;
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -471,16 +471,17 @@ browser.jar:
 *       skin/classic/browser/devtools/inspector.css                 (../shared/devtools/inspector.css)
         skin/classic/browser/devtools/profiler-stopwatch.svg        (../shared/devtools/images/profiler-stopwatch.svg)
         skin/classic/browser/devtools/profiler-stopwatch-checked.svg  (../shared/devtools/images/profiler-stopwatch-checked.svg)
         skin/classic/browser/devtools/tool-options.svg              (../shared/devtools/images/tool-options.svg)
         skin/classic/browser/devtools/tool-webconsole.svg           (../shared/devtools/images/tool-webconsole.svg)
         skin/classic/browser/devtools/tool-debugger.svg             (../shared/devtools/images/tool-debugger.svg)
         skin/classic/browser/devtools/tool-debugger-paused.svg      (../shared/devtools/images/tool-debugger-paused.svg)
         skin/classic/browser/devtools/tool-inspector.svg            (../shared/devtools/images/tool-inspector.svg)
+        skin/classic/browser/devtools/tool-shadereditor.svg         (../shared/devtools/images/tool-shadereditor.svg)
         skin/classic/browser/devtools/tool-styleeditor.svg          (../shared/devtools/images/tool-styleeditor.svg)
         skin/classic/browser/devtools/tool-storage.svg              (../shared/devtools/images/tool-storage.svg)
         skin/classic/browser/devtools/tool-profiler.svg             (../shared/devtools/images/tool-profiler.svg)
         skin/classic/browser/devtools/tool-profiler-active.svg      (../shared/devtools/images/tool-profiler-active.svg)
         skin/classic/browser/devtools/tool-network.svg              (../shared/devtools/images/tool-network.svg)
         skin/classic/browser/devtools/tool-scratchpad.svg           (../shared/devtools/images/tool-scratchpad.svg)
         skin/classic/browser/devtools/tool-webaudio.svg             (../shared/devtools/images/tool-webaudio.svg)
         skin/classic/browser/devtools/close.png                     (../shared/devtools/images/close.png)
--- a/dom/secureelement/gonk/ACEService.js
+++ b/dom/secureelement/gonk/ACEService.js
@@ -4,16 +4,17 @@
 
 /* Copyright © 2015, Deutsche Telekom, Inc. */
 
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "DOMApplicationRegistry",
                                   "resource://gre/modules/Webapps.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
                                   "resource://gre/modules/SEUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "SE", function() {
@@ -115,16 +116,21 @@ function ACEService() {
     Cc["@mozilla.org/secureelement/access-control/rules-manager;1"]
       .createInstance(Ci.nsIAccessRulesManager));
 }
 
 ACEService.prototype = {
   _rulesManagers: null,
 
   isAccessAllowed: function isAccessAllowed(localId, seType, aid) {
+    if(!Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps")) {
+      debug("Certified apps debug enabled, allowing access");
+      return Promise.resolve(true);
+    }
+
     let manifestURL = DOMApplicationRegistry.getManifestURLByLocalId(localId);
     if (!manifestURL) {
       return Promise.reject(Error("Missing manifest for app: " + localId));
     }
 
     let rulesManager = this._rulesManagers.get(seType);
     if (!rulesManager) {
       debug("App " + manifestURL + " tried to access '" + seType + "' SE" +
--- a/mobile/android/base/DynamicToolbar.java
+++ b/mobile/android/base/DynamicToolbar.java
@@ -101,21 +101,21 @@ public class DynamicToolbar {
 
     public void setVisible(boolean visible, VisibilityTransition transition) {
         ThreadUtils.assertOnUiThread();
 
         if (layerView == null) {
             return;
         }
 
-        final boolean immediate = transition == VisibilityTransition.IMMEDIATE;
+        final boolean isImmediate = transition == VisibilityTransition.IMMEDIATE;
         if (visible) {
-            layerView.getLayerMarginsAnimator().showMargins(immediate);
+            layerView.getLayerMarginsAnimator().showMargins(isImmediate);
         } else {
-            layerView.getLayerMarginsAnimator().hideMargins(immediate);
+            layerView.getLayerMarginsAnimator().hideMargins(isImmediate);
         }
     }
 
     public void setPinned(boolean pinned, PinReason reason) {
         ThreadUtils.assertOnUiThread();
 
         if (layerView == null) {
             return;
@@ -159,9 +159,9 @@ public class DynamicToolbar {
 
         @Override
         public boolean isObserver() {
             // We want to be notified of changes to be able to switch mode
             // without restarting.
             return true;
         }
     }
-}
\ No newline at end of file
+}
--- a/testing/taskcluster/tasks/builds/b2g_aries_spark_ota_debug.yml
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_ota_debug.yml
@@ -1,12 +1,12 @@
 $inherits:
   from: 'tasks/builds/b2g_aries_spark_ota_base.yml'
   variables:
-    build_name: 'aries'
+    build_name: 'aries-ota'
     build_type: 'debug'
 task:
   metadata:
     name: '[TC] B2G Aries OTA (userdebug)'
   scopes:
     - 'docker-worker:cache:build-aries-spark-ota-debug'
   payload:
     cache:
--- a/testing/taskcluster/tasks/builds/b2g_aries_spark_ota_opt.yml
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_ota_opt.yml
@@ -1,12 +1,12 @@
 $inherits:
   from: 'tasks/builds/b2g_aries_spark_ota_base.yml'
   variables:
-    build_name: 'aries'
+    build_name: 'aries-ota'
     build_type: 'opt'
 task:
   metadata:
     name: '[TC] B2G Aries OTA (user)'
   scopes:
     - 'docker-worker:cache:build-aries-spark-ota-user'
   payload:
     cache:
--- a/testing/taskcluster/tasks/builds/b2g_flame_kk_ota_debug.yml
+++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_ota_debug.yml
@@ -1,12 +1,12 @@
 $inherits:
   from: 'tasks/builds/b2g_flame_kk_ota_base.yml'
   variables:
-    build_name: 'flame-kk'
+    build_name: 'flame-kk-ota'
     build_type: 'debug'
 task:
   metadata:
     name: '[TC] B2G Flame KK OTA (userdebug)'
   scopes:
     - 'docker-worker:cache:build-flame-kk-ota-debug'
 
   payload:
--- a/testing/taskcluster/tasks/builds/b2g_flame_kk_ota_opt.yml
+++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_ota_opt.yml
@@ -1,12 +1,12 @@
 $inherits:
   from: 'tasks/builds/b2g_flame_kk_ota_base.yml'
   variables:
-    build_name: 'flame-kk'
+    build_name: 'flame-kk-ota'
     build_type: 'opt'
 task:
   metadata:
     name: '[TC] B2G Flame KK OTA (user)'
   scopes:
     - 'docker-worker:cache:build-flame-kk-ota-user'
 
   payload:
--- a/toolkit/components/places/nsLivemarkService.js
+++ b/toolkit/components/places/nsLivemarkService.js
@@ -203,18 +203,17 @@ LivemarkService.prototype = {
 
       // Create a new livemark.
       let folder = yield PlacesUtils.bookmarks.insert({
         type: PlacesUtils.bookmarks.TYPE_FOLDER,
         parentGuid: aLivemarkInfo.parentGuid,
         title: aLivemarkInfo.title,
         index: aLivemarkInfo.index,
         guid: aLivemarkInfo.guid,
-        dateAdded: toDate(aLivemarkInfo.dateAdded) || toDate(aLivemarkInfo.lastModified),
-        lastModified: toDate(aLivemarkInfo.lastModified),
+        dateAdded: toDate(aLivemarkInfo.dateAdded) || toDate(aLivemarkInfo.lastModified)
       });
 
       // Set feed and site URI annotations.
       let id = yield PlacesUtils.promiseItemId(folder.guid);
 
       // Create the internal Livemark object.
       let livemark = new Livemark({ id
                                   , title:        folder.title
@@ -228,16 +227,22 @@ LivemarkService.prototype = {
                                   , lastModified: toPRTime(folder.lastModified)
                                   });
 
       livemark.writeFeedURI(aLivemarkInfo.feedURI);
       if (aLivemarkInfo.siteURI) {
         livemark.writeSiteURI(aLivemarkInfo.siteURI);
       }
 
+      if (aLivemarkInfo.lastModified) {
+        yield PlacesUtils.bookmarks.update({ guid: folder.guid,
+                                             lastModified: toDate(aLivemarkInfo.lastModified) });
+        livemark.lastModified = aLivemarkInfo.lastModified;
+      }
+
       livemarksMap.set(folder.guid, livemark);
 
       return livemark;
     }.bind(this));
   },
 
   removeLivemark(aLivemarkInfo) {
     if (!aLivemarkInfo) {
--- a/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js
+++ b/toolkit/components/places/tests/unit/test_mozIAsyncLivemarks.js
@@ -185,16 +185,17 @@ add_task(function* test_addLivemark_noSi
   do_check_true(livemark.id > 0);
   do_check_valid_places_guid(livemark.guid);
   do_check_eq(livemark.title, "test");
   do_check_eq(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
   do_check_eq(livemark.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
   do_check_true(livemark.feedURI.equals(FEED_URI));
   do_check_eq(livemark.siteURI, null);
   do_check_true(livemark.lastModified > 0);
+  do_check_true(is_time_ordered(livemark.dateAdded, livemark.lastModified));
 
   let bookmark = yield PlacesUtils.bookmarks.fetch(livemark.guid);
   do_check_eq(livemark.index, bookmark.index);
   do_check_eq(livemark.dateAdded, bookmark.dateAdded * 1000);
 });
 
 add_task(function* test_addLivemark_succeeds() {
   let livemark = yield PlacesUtils.livemarks.addLivemark(
@@ -298,18 +299,17 @@ add_task(function* test_addLivemark_last
   let now = Date.now() * 1000;
   let livemark = yield PlacesUtils.livemarks.addLivemark(
     { title: "test"
     , parentGuid: PlacesUtils.bookmarks.unfiledGuid
     , feedURI: FEED_URI
     , lastModified: now
     });
   do_check_eq(livemark.dateAdded, now);
-  // lastModified is updated when annotations are added to the livemark.
-  do_check_true(is_time_ordered(now, livemark.lastModified));
+  do_check_eq(livemark.lastModified, now);
 });
 
 add_task(function* test_removeLivemark_emptyObject_throws() {
   try {
     yield PlacesUtils.livemarks.removeLivemark({});
     do_throw("Invoking removeLivemark with empty object should throw");
   } catch (ex) {
     do_check_eq(ex.result, Cr.NS_ERROR_INVALID_ARG);
--- a/toolkit/components/telemetry/TelemetryController.jsm
+++ b/toolkit/components/telemetry/TelemetryController.jsm
@@ -409,17 +409,17 @@ let Impl = {
     try {
       arch = Services.sysinfo.get("arch");
     } catch (e) {
       this._log.trace("assemblePing - Unable to get system architecture.", e);
     }
 
     let updateChannel = null;
     try {
-      updateChannel = UpdateChannel.get();
+      updateChannel = UpdateChannel.get(false);
     } catch (e) {
       this._log.trace("assemblePing - Unable to get update channel.", e);
     }
 
     return {
       architecture: arch,
       buildId: Services.appinfo.appBuildID,
       name: Services.appinfo.name,
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -962,17 +962,17 @@ EnvironmentCache.prototype = {
   },
 
   /**
    * Update the cached settings data.
    */
   _updateSettings: function () {
     let updateChannel = null;
     try {
-      updateChannel = UpdateChannel.get();
+      updateChannel = UpdateChannel.get(false);
     } catch (e) {}
 
     this._currentEnvironment.settings = {
       blocklistEnabled: Preferences.get(PREF_BLOCKLIST_ENABLED, true),
 #ifndef MOZ_WIDGET_ANDROID
       isDefaultBrowser: this._isDefaultBrowser(),
 #endif
       e10sEnabled: Preferences.get(PREF_E10S_ENABLED, false),
@@ -980,16 +980,18 @@ EnvironmentCache.prototype = {
       locale: getBrowserLocale(),
       update: {
         channel: updateChannel,
         enabled: Preferences.get(PREF_UPDATE_ENABLED, true),
         autoDownload: Preferences.get(PREF_UPDATE_AUTODOWNLOAD, true),
       },
       userPrefs: this._getPrefData(),
     };
+
+    this._updateSearchEngine();
   },
 
   /**
    * Update the cached profile data.
    * @returns Promise<> resolved when the I/O is complete.
    */
   _updateProfile: Task.async(function* () {
     const logger = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, "ProfileAge - ");
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -994,13 +994,37 @@ add_task(function* test_defaultSearchEng
   Services.search.defaultEngine = Services.search.getEngineByName(SEARCH_ENGINE_ID);
   yield deferred.promise;
 
   data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
 
   const EXPECTED_SEARCH_ENGINE = "other-" + SEARCH_ENGINE_ID;
   Assert.equal(data.settings.defaultSearchEngine, EXPECTED_SEARCH_ENGINE);
+  TelemetryEnvironment.unregisterChangeListener("testWatch_SearchDefault");
+
+  // Define and reset the test preference.
+  const PREF_TEST = "toolkit.telemetry.test.pref1";
+  const PREFS_TO_WATCH = new Map([
+    [PREF_TEST, TelemetryEnvironment.RECORD_PREF_STATE],
+  ]);
+  Preferences.reset(PREF_TEST);
+
+  // Set the clock in the future so our changes don't get throttled.
+  gNow = fakeNow(futureDate(gNow, 10 * MILLISECONDS_PER_MINUTE));
+  // Watch the test preference.
+  TelemetryEnvironment._watchPreferences(PREFS_TO_WATCH);
+  deferred = PromiseUtils.defer();
+  TelemetryEnvironment.registerChangeListener("testSearchEngine_pref", deferred.resolve);
+  // Trigger an environment change.
+  Preferences.set(PREF_TEST, 1);
+  yield deferred.promise;
+  TelemetryEnvironment.unregisterChangeListener("testSearchEngine_pref");
+
+  // Check that the search engine information is correctly retained when prefs change.
+  data = TelemetryEnvironment.currentEnvironment;
+  checkEnvironmentData(data);
+  Assert.equal(data.settings.defaultSearchEngine, EXPECTED_SEARCH_ENGINE);
 });
 
 add_task(function*() {
   do_test_finished();
 });
--- a/toolkit/components/viewsource/content/viewSource-content.js
+++ b/toolkit/components/viewsource/content/viewSource-content.js
@@ -880,16 +880,17 @@ let ViewSourceContent = {
   },
 
   /**
    * In-page context menu items that are injected after page load.
    */
   contextMenuItems: [
     {
       id: "goToLine",
+      accesskey: true,
       handler() {
         sendAsyncMessage("ViewSource:PromptAndGoToLine");
       }
     },
     {
       id: "wrapLongLines",
       get checked() {
         return Services.prefs.getBoolPref("view_source.wrap_long_lines");
@@ -925,16 +926,21 @@ let ViewSourceContent = {
       let item = doc.createElementNS(NS_XHTML, "menuitem");
       item.setAttribute("id", itemSpec.id);
       let labelName = `context_${itemSpec.id}_label`;
       let label = this.bundle.GetStringFromName(labelName);
       item.setAttribute("label", label);
       if ("checked" in itemSpec) {
         item.setAttribute("type", "checkbox");
       }
+      if (itemSpec.accesskey) {
+        let accesskeyName = `context_${itemSpec.id}_accesskey`;
+        item.setAttribute("accesskey",
+                          this.bundle.GetStringFromName(accesskeyName))
+      }
       menu.appendChild(item);
     });
 
     this.updateContextMenu();
   },
 
   /**
    * Update state of checkbox-style context menu items.
--- a/toolkit/devtools/server/actors/inspector.js
+++ b/toolkit/devtools/server/actors/inspector.js
@@ -270,16 +270,32 @@ var NodeActor = exports.NodeActor = prot
       if (this.rawNode.nodeValue.length > gValueSummaryLength) {
         form.shortValue = this.rawNode.nodeValue.substring(0, gValueSummaryLength);
         form.incompleteValue = true;
       } else {
         form.shortValue = this.rawNode.nodeValue;
       }
     }
 
+    // Add an extra API for custom properties added by other
+    // modules/extensions.
+    form.setFormProperty = (name, value) => {
+      if (!form.props) {
+        form.props = {};
+      }
+      form.props[name] = value;
+    };
+
+    // Fire an event so, other modules can create its own properties
+    // that should be passed to the client (within the form.props field).
+    events.emit(NodeActor, "form", {
+      target: this,
+      data: form
+    });
+
     return form;
   },
 
   get isBeforePseudoElement() {
     return this.rawNode.nodeName === "_moz_generated_content_before"
   },
 
   get isAfterPseudoElement() {
@@ -924,16 +940,28 @@ let NodeFront = protocol.FrontClass(Node
       return delayedResolve(new ShortLongString(this.shortValue));
     } else {
       return this._getNodeValue();
     }
   }, {
     impl: "_getNodeValue"
   }),
 
+  // Accessors for custom form properties.
+
+  getFormProperty: function(name) {
+    return this._form.props ? this._form.props[name] : null;
+  },
+
+  hasFormProperty: function(name) {
+    return this._form.props ? (name in this._form.props) : null;
+  },
+
+  get formProperties() this._form.props,
+
   /**
    * Return a new AttributeModificationList for this node.
    */
   startModifyingAttributes: function() {
     return AttributeModificationList(this);
   },
 
   _cacheAttributes: function() {
--- a/toolkit/locales/en-US/chrome/global/viewSource.properties
+++ b/toolkit/locales/en-US/chrome/global/viewSource.properties
@@ -8,10 +8,11 @@ invalidInputTitle = Invalid input
 invalidInputText  = The line number entered is invalid.
 outOfRangeTitle   = Line not found
 outOfRangeText    = The specified line was not found.
 statusBarLineCol  = Line %1$S, Col %2$S
 viewSelectionSourceTitle = DOM Source of Selection
 viewMathMLSourceTitle    = DOM Source of MathML
 
 context_goToLine_label        = Go to Line…
+context_goToLine_accesskey    = L
 context_wrapLongLines_label   = Wrap Long Lines
 context_highlightSyntax_label = Syntax Highlighting
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -259,26 +259,25 @@ label[disabled="true"] {
 }
 
 .wizard-box {
   padding: 20px 44px 10px;
 }
 
 .text-link {
   color: -moz-nativehyperlinktext;
-  border: 1px solid transparent;
   cursor: pointer;
 }
 
 .text-link:hover {
   text-decoration: underline;
 }
-  
-.text-link:focus {
-  border: 1px dotted -moz-DialogText;
+
+.text-link:-moz-focusring {
+  outline: 1px dotted;
 }
 
 notification > button {
   margin-top: 0;
   margin-bottom: 0;
 }
 
 popupnotificationcontent {
--- a/toolkit/themes/osx/global/global.css
+++ b/toolkit/themes/osx/global/global.css
@@ -171,36 +171,35 @@ separator.groove[orient="vertical"] {
   margin: 0 !important;
   border: none;
   padding: 0;
 }
 
 description,
 label {
   cursor: default;
+  /* FIXME: On Windows and Linux, we're using -moz-margin-end: 5px, but for
+            unknown reasons this breaks test_bug477754.xul on OS X.
+            See bug 1169606. */
+  margin: 1px 6px 2px;
 }
 
-label {
-  margin: 2px 6px;
+description {
+  margin-bottom: 4px;
 }
 
 label[disabled="true"] {
   color: GrayText;
 }
 
 .tooltip-label {
   margin: 0;
 }
 
-description {
-  margin-bottom: 4px;
-}
-
 .header {
-  margin-bottom: 6px;
   font-weight: bold;
 }
 
 .monospace {
   font-family: monospace;
 }
 
 .indent {
--- a/toolkit/themes/osx/global/notification.css
+++ b/toolkit/themes/osx/global/notification.css
@@ -107,22 +107,20 @@ notification[type="info"]:not([value="tr
 
 .popup-notification-origin:not([value]),
 .popup-notification-learnmore-link:not([href]) {
   display: none;
 }
 
 .popup-notification-origin {
   margin-bottom: .3em !important;
-  -moz-margin-start: 0 !important; /* override default label margin to match description margin */
 }
 
 .popup-notification-learnmore-link {
   margin-top: .5em !important;
-  -moz-margin-start: 0 !important; /* override default label margin to match description margin */
 }
 
 .popup-notification-button-container {
   margin-top: 17px;
 }
 
 .popup-notification-menubutton {
   -moz-appearance: none;
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -1024,16 +1024,17 @@ button.button-link:not([disabled="true"]
 /*** info UI for add-ons that have been disabled for being unsigned ***/
 
 #show-disabled-unsigned-extensions:not(:hover) {
   background-color: #fcf8ed;
 }
 
 #disabled-unsigned-addons-info {
   margin-bottom: 2em;
+  -moz-margin-end: 48px;
 }
 
 #disabled-unsigned-addons-heading {
   font-size: 1.4em;
   font-weight: bold;
   margin-bottom: .5em;
 }
 
--- a/toolkit/themes/windows/global/global.css
+++ b/toolkit/themes/windows/global/global.css
@@ -269,26 +269,25 @@ label[disabled="true"]:-moz-system-metri
 }
 
 .wizard-box {
   padding: 20px 44px 10px;
 }
 
 .text-link {
   color: -moz-nativehyperlinktext;
-  border: 1px solid transparent;
   cursor: pointer;
 }
 
 .text-link:hover {
   text-decoration: underline;
 }
 
 .text-link:-moz-focusring {
-  border: 1px dotted -moz-DialogText;
+  outline: 1px dotted;
 }
 
 popupnotificationcontent {
   margin-top: .5em;
 }
 
 /* :::::: autoscroll popup ::::: */
 
--- a/toolkit/themes/windows/global/in-content/common.css
+++ b/toolkit/themes/windows/global/in-content/common.css
@@ -51,46 +51,30 @@ xul|radio {
   }
 }
 
 xul|*.radio-icon,
 xul|*.checkbox-icon {
   -moz-margin-end: 0;
 }
 
-xul|*.text-link:-moz-focusring,
-xul|*.inline-link:-moz-focusring {
-  border: 1px dotted -moz-DialogText;
+/* Never draw a border for the focusring, use outline instead */
+xul|*.button-box,
+xul|*.menulist-label-box,
+xul|*.radio-label-box,
+xul|*.checkbox-label-box {
+  border-style: none;
 }
 
-/* Don't draw a transparent border for the focusring because when page
-   colors are disabled, the border is drawn in -moz-DialogText */
-xul|*.text-link:not(:-moz-focusring),
-xul|button:not(:-moz-focusring) > xul|*.button-box,
-xul|menulist:not(:-moz-focusring) > xul|*.menulist-label-box,
-xul|radio:not([focused="true"]) > xul|*.radio-label-box,
-xul|checkbox:not(:-moz-focusring) > xul|*.checkbox-label-box {
-  border-width: 0;
-  margin: 1px;
-}
-
-xul|*.text-link:not(:-moz-focusring) {
-  margin-top: 2px;
-  margin-right: 1px !important;
-  margin-left: 1px !important;
-  margin-bottom: 3px;
-}
-
-xul|menulist:not(:-moz-focusring) > xul|*.menulist-label-box {
-  margin: 2px;
-}
-
-xul|radio:not([focused="true"]) > xul|*.radio-label-box,
-xul|checkbox:not(:-moz-focusring) > xul|*.checkbox-label-box {
-  -moz-margin-start: 0;
+xul|*.inline-link:-moz-focusring,
+xul|button:-moz-focusring > xul|*.button-box,
+xul|menulist:-moz-focusring > xul|*.menulist-label-box,
+xul|radio[focused="true"] > xul|*.radio-label-box,
+xul|checkbox:-moz-focusring > xul|*.checkbox-label-box {
+  outline: 1px dotted;
 }
 
 /* Use a 2px border so that selected row highlight is still visible behind
     an existing high-contrast border that uses the background color */
 @media not all and (-moz-windows-default-theme) {
   xul|treechildren::-moz-tree-row(selected),
   xul|listbox xul|listitem[selected="true"] {
      border: 2px dotted Highlight;
--- a/widget/windows/InkCollector.cpp
+++ b/widget/windows/InkCollector.cpp
@@ -141,16 +141,28 @@ void InkCollector::SetTarget(HWND aTarge
       } else {
         NS_WARNING("InkCollector did not change window property successfully");
       }
       Enable(true);
     }
   }
 }
 
+void InkCollector::ClearTarget()
+{
+  if (mTargetWindow && mInkCollector) {
+    Enable(false);
+    if (S_OK == mInkCollector->put_hWnd(0)) {
+      mTargetWindow = 0;
+    } else {
+      NS_WARNING("InkCollector did not clear window property successfully");
+    }
+  }
+}
+
 // The display and the digitizer have quite different properties.
 // The display has CursorMustTouch, the mouse pointer alway touches the display surface.
 // The digitizer lists Integrated and HardProximity.
 // When the stylus is in the proximity of the tablet its movements are also detected.
 // An external tablet will only list HardProximity.
 bool InkCollector::IsHardProximityTablet(IInkTablet* aTablet) const
 {
   if (aTablet) {
@@ -182,25 +194,30 @@ HRESULT __stdcall InkCollector::QueryInt
     // It is necessary to call Initialize() before invoking this method.
     NS_ASSERTION(mMarshaller, "Free threaded marshaller is null!");
     // Use free threaded marshalling.
     result = mMarshaller->QueryInterface(aRiid, aObject);
   }
   return result;
 }
 
+// To avoid a memory leak you must explicitly call the Dispose
+// method on any InkCollector object to which an event handler
+// has been attached, before the object goes out of scope.
+// https://msdn.microsoft.com/en-us/library/dd187726.aspx
 HRESULT InkCollector::Invoke(DISPID aDispIdMember, REFIID /*aRiid*/,
                              LCID /*aId*/, WORD /*wFlags*/,
                              DISPPARAMS* aDispParams, VARIANT* /*aVarResult*/,
                              EXCEPINFO* /*aExcepInfo*/, UINT* /*aArgErr*/)
 {
   switch (aDispIdMember) {
     case DISPID_ICECursorOutOfRange: {
       if (aDispParams && aDispParams->cArgs) {
         CursorOutOfRange(static_cast<IInkCursor*>(aDispParams->rgvarg[0].pdispVal));
+        ClearTarget();
       }
       break;
     }
   };
   // Release should be called after all usage of this method.
   NS_RELEASE_THIS();
   return S_OK;
 }
@@ -213,11 +230,11 @@ void InkCollector::CursorOutOfRange(IInk
   }
   // All events should be suppressed except
   // from tablets with hard proximity.
   if (!IsHardProximityTablet(curTablet)) {
     return;
   }
   // Notify current target window.
   if (mTargetWindow) {
-    ::PostMessage(mTargetWindow, MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER, 0, 0);
+    ::SendMessage(mTargetWindow, MOZ_WM_PEN_LEAVES_HOVER_OF_DIGITIZER, 0, 0);
   }
 }
--- a/widget/windows/InkCollector.h
+++ b/widget/windows/InkCollector.h
@@ -48,24 +48,25 @@ protected:
                     DISPPARAMS* aDispParams, VARIANT* aVarResult,
                     EXCEPINFO* aExcepInfo, UINT* aArgErr);
 
   // InkCollector
   virtual ~InkCollector();
   void Initialize();
   void OnInitialize();
   void Enable(bool aNewState);
+  void ClearTarget();
   void CursorOutOfRange(IInkCursor* aCursor) const;
   bool IsHardProximityTablet(IInkTablet* aTablet) const;
 
 private:
   nsRefPtr<IUnknown>          mMarshaller;
   nsRefPtr<IInkCollector>     mInkCollector;
   nsRefPtr<IConnectionPoint>  mConnectionPoint;
 
-  uint32_t            mRefCount         = 0;
-  DWORD               mCookie           = 0;
-  HWND                mTargetWindow     = 0;
-  bool                mComInitialized   = false;
-  bool                mEnabled          = false;
+  HWND                        mTargetWindow     = 0;
+  DWORD                       mCookie           = 0;
+  uint32_t                    mRefCount         = 0;
+  bool                        mComInitialized   = false;
+  bool                        mEnabled          = false;
 };
 
 #endif // nsInkCollector_h_