Merge m-c to inbound a=merge
authorWes Kocher <wkocher@mozilla.com>
Mon, 25 Aug 2014 17:25:09 -0700
changeset 223228 0843c26857a9d0534a461ec3fdacfd8b6112167e
parent 223227 af7832580b3ad586c7db86159eb64e755b1728e1 (current diff)
parent 223129 dc352a7bf234df7682ceedbf70b1f676e82e8171 (diff)
child 223229 e1174da6b7078a99c67f439f178e8558ba5c8473
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.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
--- 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="53a59364ce4f14068034c8d6fe01f4f6b9f78f23">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a567a787b5ac3e0cb663aa6464b18a24ec764409"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <!-- 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="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <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="53a59364ce4f14068034c8d6fe01f4f6b9f78f23">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a567a787b5ac3e0cb663aa6464b18a24ec764409"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "5efa211f0198ab15798b456445f163d57e735cdb", 
+    "revision": "0ce5a025c89f6120b55498528323a8a973dd117e", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4d1d0ea5a82cddeeab497774cfa1703639e3c7d9"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -1,13 +1,16 @@
 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 # 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/.
 
+# NB: IF YOU ADD ITEMS TO THIS FILE, PLEASE UPDATE THE WHITELIST IN
+# BrowserUITelemetry.jsm. SEE BUG 991757 FOR DETAILS.
+
       <menugroup id="context-navigation">
         <menuitem id="context-back"
                   class="menuitem-iconic"
                   tooltiptext="&backButton.tooltip;"
                   aria-label="&backCmd.label;"
                   command="Browser:BackOrBackDuplicate"
                   onclick="checkForMiddleClick(this, event);"/>
         <menuitem id="context-forward"
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -33,23 +33,31 @@ nsContextMenu.prototype = {
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
 
     this.isContentSelected = this.isContentSelection();
     this.onPlainTextLink = false;
 
     // Initialize (disable/remove) menu items.
     this.initItems();
+
+    // Register this opening of the menu with telemetry:
+    this._checkTelemetryForMenu(aXulMenu);
   },
 
   hiding: function CM_hiding() {
     gContextMenuContentData = null;
     InlineSpellCheckerUI.clearSuggestionsFromMenu();
     InlineSpellCheckerUI.clearDictionaryListFromMenu();
     InlineSpellCheckerUI.uninit();
+
+    // This handler self-deletes, only run it if it is still there:
+    if (this._onPopupHiding) {
+      this._onPopupHiding();
+    }
   },
 
   initItems: function CM_initItems() {
     this.initPageMenuSeparator();
     this.initOpenItems();
     this.initNavigationItems();
     this.initViewItems();
     this.initMiscItems();
@@ -1698,10 +1706,81 @@ nsContextMenu.prototype = {
       engineName = ss.defaultEngine.name;
 
     // format "Search <engine> for <selection>" string to show in menu
     var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch",
                                                         [engineName,
                                                          selectedText]);
     menuItem.label = menuLabel;
     menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey");
-  }
+  },
+
+  _getTelemetryClickInfo: function(aXulMenu) {
+    this._onPopupHiding = () => {
+      aXulMenu.ownerDocument.removeEventListener("command", activationHandler, true);
+      aXulMenu.removeEventListener("popuphiding", this._onPopupHiding, true);
+      delete this._onPopupHiding;
+
+      let eventKey = [
+          this._telemetryPageContext,
+          this._telemetryHadCustomItems ? "withcustom" : "withoutcustom"
+      ];
+      let target = this._telemetryClickID || "close-without-interaction";
+      BrowserUITelemetry.registerContextMenuInteraction(eventKey, target);
+    };
+    let activationHandler = (e) => {
+      // Deal with command events being routed to command elements; figure out
+      // what triggered the event (which will have the right e.target)
+      if (e.sourceEvent) {
+        e = e.sourceEvent;
+      }
+      // Target should be in the menu (this catches using shortcuts for items
+      // not in the menu while the menu is up)
+      if (!aXulMenu.contains(e.target)) {
+        return;
+      }
+
+      // Check if this is a page menu item:
+      if (e.target.hasAttribute(PageMenu.GENERATEDITEMID_ATTR)) {
+        this._telemetryClickID = "custom-page-item";
+      } else {
+        this._telemetryClickID = (e.target.id || "unknown").replace(/^context-/i, "");
+      }
+    };
+    aXulMenu.ownerDocument.addEventListener("command", activationHandler, true);
+    aXulMenu.addEventListener("popuphiding", this._onPopupHiding, true);
+  },
+
+  _getTelemetryPageContextInfo: function() {
+    if (this.isContentSelected) {
+      return "selection";
+    }
+    if (this.onLink) {
+      if (this.onImage || this.onCanvas) {
+        return "image-link";
+      }
+      return "link";
+    }
+    if (this.onImage) {
+      return "image"
+    }
+    if (this.onCanvas) {
+      return "canvas";
+    }
+    if (this.onVideo || this.onAudio) {
+      return "media";
+    }
+    if (this.onTextInput) {
+      return "input";
+    }
+    if (this.onSocial) {
+      return "social";
+    }
+    return "other";
+  },
+
+  _checkTelemetryForMenu: function(aXulMenu) {
+    this._telemetryClickID = null;
+    this._telemetryPageContext = this._getTelemetryPageContextInfo();
+    this._telemetryHadCustomItems = this.hasPageMenu;
+    this._getTelemetryClickInfo(aXulMenu);
+  },
 };
--- a/browser/devtools/inspector/test/browser_inspector_initialization.js
+++ b/browser/devtools/inspector/test/browser_inspector_initialization.js
@@ -114,11 +114,14 @@ function* clickOnInspectMenuItem(node) {
   info("Clicking on 'Inspect Element' context menu item of " + node);
   document.popupNode = node;
   var contentAreaContextMenu = getNode("#contentAreaContextMenu", { document });
   var contextMenu = new nsContextMenu(contentAreaContextMenu);
 
   info("Triggering inspect action.");
   yield contextMenu.inspectNode();
 
+  // Clean up context menu:
+  contextMenu.hiding();
+
   info("Waiting for inspector to update.");
   yield getActiveInspector().once("inspector-updated");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_content_02.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_content_02.js
@@ -26,16 +26,20 @@ let test = asyncTest(function*() {
 
   info("Opening the inspector using the content context-menu");
   let onInspectorReady = gDevTools.once("inspector-ready");
 
   document.popupNode = element;
   let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
   let contextMenu = new nsContextMenu(contentAreaContextMenu);
   yield contextMenu.inspectNode();
+
+  // Clean up context menu:
+  contextMenu.hiding();
+
   yield onInspectorReady;
 
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   let toolbox = gDevTools.getToolbox(target);
 
   info("Getting the inspector and making sure it is fully updated");
   let inspector = toolbox.getPanel("inspector");
   yield inspector.once("inspector-updated");
--- a/browser/devtools/webide/content/webide.js
+++ b/browser/devtools/webide/content/webide.js
@@ -556,21 +556,17 @@ let UI = {
         debugCmd.removeAttribute("disabled");
       } else {
         stopCmd.setAttribute("disabled", "true");
         debugCmd.setAttribute("disabled", "true");
       }
 
       // If connected and a project is selected
       if (AppManager.selectedProject.type == "runtimeApp") {
-        if (isProjectRunning) {
-          playCmd.setAttribute("disabled", "true");
-        } else {
-          playCmd.removeAttribute("disabled");
-        }
+        playCmd.removeAttribute("disabled");
       } else if (AppManager.selectedProject.type == "mainProcess") {
         playCmd.setAttribute("disabled", "true");
         stopCmd.setAttribute("disabled", "true");
       } else {
         if (AppManager.selectedProject.errorsCount == 0) {
           playCmd.removeAttribute("disabled");
         } else {
           playCmd.setAttribute("disabled", "true");
--- a/browser/devtools/webide/modules/app-manager.js
+++ b/browser/devtools/webide/modules/app-manager.js
@@ -378,17 +378,21 @@ exports.AppManager = AppManager = {
 
   runRuntimeApp: function() {
     if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
       return promise.reject("attempting to run a non-runtime app");
     }
     let client = this.connection.client;
     let actor = this._listTabsResponse.webappsActor;
     let manifest = this.getProjectManifestURL(this.selectedProject);
-    return AppActorFront.launchApp(client, actor, manifest);
+    if (!this.isProjectRunning()) {
+      return AppActorFront.launchApp(client, actor, manifest);
+    } else {
+      return AppActorFront.reloadApp(client, actor, manifest);
+    }
   },
 
   installAndRunProject: function() {
     let project = this.selectedProject;
 
     if (!project || (project.type != "packaged" && project.type != "hosted")) {
       console.error("Can't install project. Unknown type of project.");
       return promise.reject("Can't install");
--- a/browser/devtools/webide/themes/webide.css
+++ b/browser/devtools/webide/themes/webide.css
@@ -130,17 +130,17 @@ window.busy-determined #action-busy-unde
 /* Panels */
 
 panel > vbox {
   overflow-x: hidden;
 }
 
 panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 12px 0;
-  width: 200px;
+  min-width: 200px;
 }
 
 .panel-item {
   padding: 3px 12px;
   margin: 0;
   -moz-appearance: none;
   border-width: 0;
   font-size: 13px; /* height of the icons */
--- a/browser/modules/BrowserUITelemetry.jsm
+++ b/browser/modules/BrowserUITelemetry.jsm
@@ -165,16 +165,18 @@ const BUCKET_PREFIX = "bucket_";
 // Standard separator to use between different parts of a bucket name, such
 // as primary name and the time step string.
 const BUCKET_SEPARATOR = "|";
 
 this.BrowserUITelemetry = {
   init: function() {
     UITelemetry.addSimpleMeasureFunction("toolbars",
                                          this.getToolbarMeasures.bind(this));
+    UITelemetry.addSimpleMeasureFunction("contextmenu",
+                                         this.getContextMenuInfo.bind(this));
     // Ensure that UITour.jsm remains lazy-loaded, yet always registers its
     // simple measure function with UITelemetry.
     UITelemetry.addSimpleMeasureFunction("UITour",
                                          () => UITour.getTelemetry());
 
     Services.obs.addObserver(this, "sessionstore-windows-restored", false);
     Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
     CustomizableUI.addListener(this);
@@ -215,21 +217,23 @@ this.BrowserUITelemetry = {
    * example["c"]++;
    *
    * Subsequent repetitions of these last two lines would
    * simply result in the c value being incremented again
    * and again.
    *
    * @param aKeys the Array of keys to chain Objects together with.
    * @param aEndWith the value to assign to the last key.
+   * @param aRoot the root object onto which we create/get the object chain
+   *              designated by aKeys.
    * @returns a reference to the second last object in the chain -
    *          so in our example, that'd be "b".
    */
-  _ensureObjectChain: function(aKeys, aEndWith) {
-    let current = this._countableEvents;
+  _ensureObjectChain: function(aKeys, aEndWith, aRoot) {
+    let current = aRoot;
     let parent = null;
     aKeys.unshift(this._bucket);
     for (let [i, key] of Iterator(aKeys)) {
       if (!(key in current)) {
         if (i == aKeys.length - 1) {
           current[key] = aEndWith;
         } else {
           current[key] = {};
@@ -237,18 +241,18 @@ this.BrowserUITelemetry = {
       }
       parent = current;
       current = current[key];
     }
     return parent;
   },
 
   _countableEvents: {},
-  _countEvent: function(aKeyArray) {
-    let countObject = this._ensureObjectChain(aKeyArray, 0);
+  _countEvent: function(aKeyArray, root=this._countableEvents) {
+    let countObject = this._ensureObjectChain(aKeyArray, 0, root);
     let lastItemKey = aKeyArray[aKeyArray.length - 1];
     countObject[lastItemKey]++;
   },
 
   _countMouseUpEvent: function(aCategory, aAction, aButton) {
     const BUTTONS = ["left", "middle", "right"];
     let buttonKey = BUTTONS[aButton];
     if (buttonKey) {
@@ -582,16 +586,64 @@ this.BrowserUITelemetry = {
       this._durations.customization.push({
         duration: duration,
         bucket: durationMap.customization.bucket,
       });
       delete durationMap.customization;
     }
   },
 
+  _contextMenuItemWhitelist: new Set([
+    "close-without-interaction", // for closing the menu without clicking it.
+    "custom-page-item", // The ID we use for page-provided items
+    "unknown", // The bucket for stuff with no id.
+    // Everything we know of so far (which will exclude add-on items):
+    "navigation", "back", "forward", "reload", "stop", "bookmarkpage",
+    "spell-no-suggestions", "spell-add-to-dictionary",
+    "spell-undo-add-to-dictionary", "openlinkincurrent", "openlinkintab",
+    "openlink", "openlinkprivate", "bookmarklink", "sharelink", "savelink",
+    "marklinkMenu", "copyemail", "copylink", "media-play", "media-pause",
+    "media-mute", "media-unmute", "media-playbackrate",
+    "media-playbackrate-050x", "media-playbackrate-100x",
+    "media-playbackrate-150x", "media-playbackrate-200x",
+    "media-showcontrols", "media-hidecontrols", "video-showstats",
+    "video-hidestats", "video-fullscreen", "leave-dom-fullscreen",
+    "reloadimage", "viewimage", "viewvideo", "copyimage-contents", "copyimage",
+    "copyvideourl", "copyaudiourl", "saveimage", "shareimage", "sendimage",
+    "setDesktopBackground", "viewimageinfo", "viewimagedesc", "savevideo",
+    "sharevideo", "saveaudio", "video-saveimage", "sendvideo", "sendaudio",
+    "ctp-play", "ctp-hide", "sharepage", "savepage", "markpageMenu",
+    "viewbgimage", "undo", "cut", "copy", "paste", "delete", "selectall",
+    "keywordfield", "searchselect", "shareselect", "frame", "showonlythisframe",
+    "openframeintab", "openframe", "reloadframe", "bookmarkframe", "saveframe",
+    "printframe", "viewframesource", "viewframeinfo",
+    "viewpartialsource-selection", "viewpartialsource-mathml",
+    "viewsource", "viewinfo", "spell-check-enabled",
+    "spell-add-dictionaries-main", "spell-dictionaries",
+    "spell-dictionaries-menu", "spell-add-dictionaries",
+    "bidi-text-direction-toggle", "bidi-page-direction-toggle", "inspect",
+  ]),
+
+  _contextMenuInteractions: {},
+
+  registerContextMenuInteraction: function(keys, itemID) {
+    if (itemID) {
+      if (!this._contextMenuItemWhitelist.has(itemID)) {
+        itemID = "other-item";
+      }
+      keys.push(itemID);
+    }
+
+    this._countEvent(keys, this._contextMenuInteractions);
+  },
+
+  getContextMenuInfo: function() {
+    return this._contextMenuInteractions;
+  },
+
   _bucket: BUCKET_DEFAULT,
   _bucketTimer: null,
 
   /**
    * Default bucket name, when no other bucket is active.
    */
   get BUCKET_DEFAULT() BUCKET_DEFAULT,
 
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -89,22 +89,23 @@
 }
 
 #customization-palette,
 #customization-empty {
   padding: 0 25px 25px;
 }
 
 #customization-header {
-  font-size: 1.5em;
-  line-height: 1.5em;
-  color: rgb(64,100,128);
-  font-weight: lighter;
-  margin-bottom: 1em;
-  padding: 25px 25px 0;
+  font-size: 1.75em;
+  line-height: 1.75em;
+  color: #666;
+  font-weight: 200;
+  margin: 25px 25px 12px;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #e5e5e5;
 }
 
 #customization-panel-container {
   padding: 15px 25px 25px;
   background-image: linear-gradient(to bottom, #3e86ce, #3878ba);
 }
 
 #main-window:-moz-any([customize-entering],[customize-entered]) #browser-bottombox,
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -393,21 +393,37 @@ nsDOMCameraControl::GetIsoMode(nsString&
 void
 nsDOMCameraControl::SetIsoMode(const nsAString& aIsoMode, ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
   aRv = mCameraControl->Set(CAMERA_PARAM_ISOMODE, aIsoMode);
 }
 
 double
+nsDOMCameraControl::GetPictureQuality(ErrorResult& aRv)
+{
+  MOZ_ASSERT(mCameraControl);
+
+  double quality;
+  aRv = mCameraControl->Get(CAMERA_PARAM_PICTURE_QUALITY, quality);
+  return quality;
+}
+void
+nsDOMCameraControl::SetPictureQuality(double aQuality, ErrorResult& aRv)
+{
+  MOZ_ASSERT(mCameraControl);
+  aRv = mCameraControl->Set(CAMERA_PARAM_PICTURE_QUALITY, aQuality);
+}
+
+double
 nsDOMCameraControl::GetZoom(ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
 
-  double zoom;
+  double zoom = 1.0;
   aRv = mCameraControl->Get(CAMERA_PARAM_ZOOM, zoom);
   return zoom;
 }
 
 void
 nsDOMCameraControl::SetZoom(double aZoom, ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -77,16 +77,18 @@ public:
   double GetFocusDistanceOptimum(ErrorResult& aRv);
   double GetFocusDistanceFar(ErrorResult& aRv);
   void SetExposureCompensation(double aCompensation, ErrorResult& aRv);
   double GetExposureCompensation(ErrorResult& aRv);
   int32_t SensorAngle();
   already_AddRefed<dom::CameraCapabilities> Capabilities();
   void GetIsoMode(nsString& aMode, ErrorResult& aRv);
   void SetIsoMode(const nsAString& aMode, ErrorResult& aRv);
+  double GetPictureQuality(ErrorResult& aRv);
+  void SetPictureQuality(double aQuality, ErrorResult& aRv);
 
   // Unsolicited event handlers.
   dom::CameraShutterCallback* GetOnShutter();
   void SetOnShutter(dom::CameraShutterCallback* aCb);
   dom::CameraClosedCallback* GetOnClosed();
   void SetOnClosed(dom::CameraClosedCallback* aCb);
   dom::CameraRecorderStateChange* GetOnRecorderStateChange();
   void SetOnRecorderStateChange(dom::CameraRecorderStateChange* aCb);
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -172,28 +172,32 @@ nsGonkCameraControl::Initialize()
   nsString luminance; // check for support
   mParams.Get(CAMERA_PARAM_LUMINANCE, luminance);
   mLuminanceSupported = !luminance.IsEmpty();
 
   nsString flashMode;
   mParams.Get(CAMERA_PARAM_FLASHMODE, flashMode);
   mFlashSupported = !flashMode.IsEmpty();
 
+  double quality; // informational only
+  mParams.Get(CAMERA_PARAM_PICTURE_QUALITY, quality);
+
   DOM_CAMERA_LOGI(" - maximum metering areas:        %u\n", mCurrentConfiguration.mMaxMeteringAreas);
   DOM_CAMERA_LOGI(" - maximum focus areas:           %u\n", mCurrentConfiguration.mMaxFocusAreas);
   DOM_CAMERA_LOGI(" - default picture size:          %u x %u\n",
     mLastPictureSize.width, mLastPictureSize.height);
+  DOM_CAMERA_LOGI(" - default picture file format:   %s\n",
+    NS_ConvertUTF16toUTF8(mFileFormat).get());
+  DOM_CAMERA_LOGI(" - default picture quality:       %f\n", quality);
   DOM_CAMERA_LOGI(" - default thumbnail size:        %u x %u\n",
     mLastThumbnailSize.width, mLastThumbnailSize.height);
   DOM_CAMERA_LOGI(" - default preview size:          %u x %u\n",
     mCurrentConfiguration.mPreviewSize.width, mCurrentConfiguration.mPreviewSize.height);
   DOM_CAMERA_LOGI(" - default video recorder size:   %u x %u\n",
     mLastRecorderSize.width, mLastRecorderSize.height);
-  DOM_CAMERA_LOGI(" - default picture file format:   %s\n",
-    NS_ConvertUTF16toUTF8(mFileFormat).get());
   DOM_CAMERA_LOGI(" - luminance reporting:           %ssupported\n",
     mLuminanceSupported ? "" : "NOT ");
   if (mFlashSupported) {
     DOM_CAMERA_LOGI(" - flash:                         supported, default mode '%s'\n",
       NS_ConvertUTF16toUTF8(flashMode).get());
   } else {
     DOM_CAMERA_LOGI(" - flash:                         NOT supported\n");
   }
--- a/dom/camera/GonkCameraParameters.cpp
+++ b/dom/camera/GonkCameraParameters.cpp
@@ -110,16 +110,18 @@ GonkCameraParameters::Parameters::GetTex
     case CAMERA_PARAM_LUMINANCE:
       return "luminance-condition";
     case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
       // Not every platform defines KEY_QC_HDR_NEED_1X;
       // for those that don't, we use the raw string key.
       return "hdr-need-1x";
     case CAMERA_PARAM_RECORDINGHINT:
       return KEY_RECORDING_HINT;
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      return KEY_JPEG_QUALITY;
 
     case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
       return KEY_SUPPORTED_PREVIEW_SIZES;
     case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
       return KEY_SUPPORTED_PICTURE_SIZES;
     case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
       return KEY_SUPPORTED_VIDEO_SIZES;
     case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
@@ -656,16 +658,29 @@ GonkCameraParameters::SetTranslated(uint
             } else {
               top = index - 1;
             }
           }
         }
         DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
       }
       return SetImpl(CAMERA_PARAM_ZOOM, index);
+
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      {
+        // Convert aValue [0.0..1.0] to nearest index in the range [1..100].
+        index = (aValue + 0.005) * 99.0 + 1.0;
+        if (aValue < 0.0) {
+          index = 1;
+        } else if (aValue > 1.0) {
+          index = 100;
+        }
+        DOM_CAMERA_LOGI("Picture quality = %f --> index = %d\n", aValue, index);
+      }
+      return SetImpl(CAMERA_PARAM_PICTURE_QUALITY, index);
   }
 
   return SetImpl(aKey, aValue);
 }
 
 nsresult
 GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
 {
@@ -720,16 +735,29 @@ GonkCameraParameters::GetTranslated(uint
       }
       rv = GetImpl(aKey, index);
       if (NS_SUCCEEDED(rv)) {
         val = index * mExposureCompensationStep;
         DOM_CAMERA_LOGI("exposure compensation (aKey=%d): index=%d --> EV=%f\n", aKey, index, val);
       }
       break;
 
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      // Convert index [1..100] to a quality value [0.0..1.0].
+      rv = GetImpl(aKey, index);
+      if (index < 2) {
+        val = 0.0;
+      } else if (index > 99) {
+        val = 1.0;
+      } else {
+        val = static_cast<double>(index - 1) / 99.0;
+      }
+      DOM_CAMERA_LOGI("index = %d --> picture quality = %f\n", index, val);
+      break;
+
     default:
       rv = GetImpl(aKey, val);
       break;
   }
 
   if (NS_SUCCEEDED(rv)) {
     aValue = val;
   }
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -28,16 +28,17 @@ enum {
   CAMERA_PARAM_PREVIEWFORMAT,
   CAMERA_PARAM_PREVIEWFRAMERATE,
   CAMERA_PARAM_VIDEOSIZE,
   CAMERA_PARAM_PICTURE_SIZE,
   CAMERA_PARAM_PICTURE_FILEFORMAT,
   CAMERA_PARAM_PICTURE_ROTATION,
   CAMERA_PARAM_PICTURE_LOCATION,
   CAMERA_PARAM_PICTURE_DATETIME,
+  CAMERA_PARAM_PICTURE_QUALITY,
   CAMERA_PARAM_EFFECT,
   CAMERA_PARAM_WHITEBALANCE,
   CAMERA_PARAM_SCENEMODE,
   CAMERA_PARAM_FLASHMODE,
   CAMERA_PARAM_FOCUSMODE,
   CAMERA_PARAM_ZOOM,
   CAMERA_PARAM_METERINGAREAS,
   CAMERA_PARAM_FOCUSAREAS,
--- a/dom/camera/test/test_camera.html
+++ b/dom/camera/test/test_camera.html
@@ -154,19 +154,33 @@ var Camera = {
     ok(camcap.isoModes.length == 0, "ISO modes length = " + camcap.isoModes.length);
 
     // The emulator doesn't support zoom, so these parameters will be very constrained
     // For more ambitious tests, see test_camera_fake_parameters.html
     ok(Camera._zoomRatios.length == 1, "zoom ratios length = " + Camera._zoomRatios.length);
     ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
     // Test snapping to supported values
     Camera.cameraObj.zoom = 0.9;
-    ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
+    ok(Camera.cameraObj.zoom == 1.0, "zoom (lower limit) = " + Camera.cameraObj.zoom);
     Camera.cameraObj.zoom = 1.1;
-    ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
+    ok(Camera.cameraObj.zoom == 1.0, "zoom (upper limit) = " + Camera.cameraObj.zoom);
+
+    // Check image quality handling
+    Camera.cameraObj.pictureQuality = 0.0;
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = -0.1;
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality (minimum limit) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = -Math.pow(2, 80);
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality (BIG negative) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = 1.0;
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = 1.1;
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality (maximum limit) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = Math.pow(2, 80);
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality (BIG positive) = " + Camera.cameraObj.pictureQuality);
 
     Camera._tests = new Array();
     for (var i in Camera._pictureSizes) {
       for (var l in Camera._fileFormats) {
         var config = {
           pictureSize: Camera._pictureSizes[i],
           fileFormat: Camera._fileFormats[l]
         };
--- a/dom/webidl/CameraControl.webidl
+++ b/dom/webidl/CameraControl.webidl
@@ -252,16 +252,26 @@ interface CameraControl : MediaStream
   /* the size of the picture to be returned by a call to takePicture();
      an object with 'height' and 'width' properties that corresponds to
      one of the options returned by capabilities.pictureSizes. */
   [Throws]
   CameraSize getPictureSize();
   [Throws]
   void setPictureSize(optional CameraSize size);
 
+  /* if the image blob to be returned by takePicture() supports lossy
+     compression, this setting controls the quality-size trade-off;
+     valid values range from 0.0 for smallest size/worst quality to 1.0
+     for largest size/best quality. Note that depending on the range of
+     values supported by the underlying platform, this attribute may not
+     'get' the exact value that was previously 'set'. If this setting is
+     not supported, it is ignored. */
+  [Throws]
+  attribute double           pictureQuality;
+
   /* the size of the thumbnail to be included in the picture returned
      by a call to takePicture(), assuming the chosen fileFormat supports
      one; an object with 'height' and 'width' properties that corresponds
      to one of the options returned by capabilities.pictureSizes.
 
      this setting should be considered a hint: the implementation will
      respect it when possible, and override it if necessary. */
   [Throws]
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -2512,16 +2512,19 @@ public class BrowserApp extends GeckoApp
                 url = urlFromReader;
             }
         }
 
         // Disable share menuitem for about:, chrome:, file:, and resource: URIs
         final boolean inGuestMode = GeckoProfile.get(this).inGuestMode();
         share.setVisible(!inGuestMode);
         share.setEnabled(StringUtils.isShareableUrl(url) && !inGuestMode);
+        MenuUtils.safeSetEnabled(aMenu, R.id.apps, !inGuestMode);
+        MenuUtils.safeSetEnabled(aMenu, R.id.addons, !inGuestMode);
+        MenuUtils.safeSetEnabled(aMenu, R.id.downloads, !inGuestMode);
 
         // NOTE: Use MenuUtils.safeSetEnabled because some actions might
         // be on the BrowserToolbar context menu
         MenuUtils.safeSetEnabled(aMenu, R.id.page, !isAboutHome(tab));
         MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, tab.hasFeeds());
         MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, tab.hasOpenSearch());
         MenuUtils.safeSetEnabled(aMenu, R.id.site_settings, !isAboutHome(tab));
         MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, !isAboutHome(tab));
--- a/mobile/android/locales/en-US/chrome/webapp.properties
+++ b/mobile/android/locales/en-US/chrome/webapp.properties
@@ -50,8 +50,10 @@ installUpdateMessage2=Touch to install u
 # example: 3 updates failed
 retrievalFailedTitle=#1 update failed;#1 updates failed
 
 # LOCALIZATION NOTE (retrievalFailedMessage): Semi-colon list of plural forms.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # %1$S is a comma-separated list of apps for which retrieval failed.
 # example: Failed to retrieve updates for Foo, Bar, Baz
 retrievalFailedMessage=Failed to retrieve update for %1$S;Failed to retrieve updates for %1$S
+
+webappsDisabledInGuest=Installing apps is disabled in guest sessions
--- a/mobile/android/modules/WebappManager.jsm
+++ b/mobile/android/modules/WebappManager.jsm
@@ -84,16 +84,22 @@ this.WebappManager = {
       DOMApplicationRegistry.doInstallPackage(aMessage, aMessageManager);
       return;
     }
 
     this._installApk(aMessage, aMessageManager);
   },
 
   _installApk: function(aMessage, aMessageManager) { return Task.spawn((function*() {
+    if (this.inGuestSession()) {
+      aMessage.error = Strings.GetStringFromName("webappsDisabledInGuest"),
+      aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
+      return;
+    }
+
     let filePath;
 
     try {
       filePath = yield this._downloadApk(aMessage.app.manifestURL);
     } catch(ex) {
       aMessage.error = ex;
       aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
       debug("error downloading APK: " + ex);
@@ -252,16 +258,20 @@ this.WebappManager = {
       // to ensure the user can always remove an app from the registry (and thus
       // about:apps) even if it's out of sync with installed APKs.
       debug("APK not installed; proceeding directly to removal from registry");
       DOMApplicationRegistry.doUninstall(aData, aMessageManager);
     }
 
   }),
 
+  inGuestSession: function() {
+    return Services.wm.getMostRecentWindow("navigator:browser").BrowserApp.isGuest;
+  },
+
   autoInstall: function(aData) {
     debug("autoInstall " + aData.manifestURL);
 
     // If the app is already installed, update the existing installation.
     // We should be able to use DOMApplicationRegistry.getAppByManifestURL,
     // but it returns a mozIApplication, while _autoUpdate needs the original
     // object from DOMApplicationRegistry.webapps in order to modify it.
     for (let [ , app] in Iterator(DOMApplicationRegistry.webapps)) {
--- a/python/mozboot/mozboot/bootstrap.py
+++ b/python/mozboot/mozboot/bootstrap.py
@@ -54,17 +54,17 @@ class Bootstrapper(object):
                 # Most Linux Mint editions are based on Ubuntu; one is based on
                 # Debian, and reports this in dist_id
                 if dist_id == 'debian':
                     cls = DebianBootstrapper
                 else:
                     cls = UbuntuBootstrapper
             elif distro == 'Ubuntu':
                 cls = UbuntuBootstrapper
-            elif distro == 'Elementary':
+            elif distro in ('Elementary OS', 'Elementary'):
                 cls = UbuntuBootstrapper
             else:
                 raise NotImplementedError('Bootstrap support for this Linux '
                                           'distro not yet available.')
 
             args['version'] = version
             args['dist_id'] = dist_id
 
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -1960,39 +1960,54 @@ ThreadActor.prototype = {
   createValueGrip: function (aValue, aPool=false) {
     if (!aPool) {
       aPool = this._pausePool;
     }
 
     switch (typeof aValue) {
       case "boolean":
         return aValue;
+
       case "string":
         if (this._stringIsLong(aValue)) {
           return this.longStringGrip(aValue, aPool);
         }
         return aValue;
+
       case "number":
         if (aValue === Infinity) {
           return { type: "Infinity" };
         } else if (aValue === -Infinity) {
           return { type: "-Infinity" };
         } else if (Number.isNaN(aValue)) {
           return { type: "NaN" };
         } else if (!aValue && 1 / aValue === -Infinity) {
           return { type: "-0" };
         }
         return aValue;
+
       case "undefined":
         return { type: "undefined" };
+
       case "object":
         if (aValue === null) {
           return { type: "null" };
         }
         return this.objectGrip(aValue, aPool);
+
+      case "symbol":
+        let form = {
+          type: "symbol"
+        };
+        let name = getSymbolName(aValue);
+        if (name !== undefined) {
+          form.name = this.createValueGrip(name);
+        }
+        return form;
+
       default:
         dbg_assert(false, "Failed to provide a grip for: " + aValue);
         return null;
     }
   },
 
   /**
    * Return a protocol completion value representing the given
@@ -5425,16 +5440,23 @@ function makeDebuggeeValueIfNeeded(obj, 
   return value;
 }
 
 function getInnerId(window) {
   return window.QueryInterface(Ci.nsIInterfaceRequestor).
                 getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
 };
 
+const symbolProtoToString = Symbol.prototype.toString;
+
+function getSymbolName(symbol) {
+  const name = symbolProtoToString.call(symbol).slice("Symbol(".length, -1);
+  return name || undefined;
+}
+
 exports.register = function(handle) {
   ThreadActor.breakpointStore = new BreakpointStore();
   ThreadSources._blackBoxedSources = new Set(["self-hosted"]);
   ThreadSources._prettyPrintedSources = new Map();
 };
 
 exports.unregister = function(handle) {
   ThreadActor.breakpointStore = null;
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/unit/test_symbols-01.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that we can represent ES6 Symbols over the RDP.
+ */
+
+const URL = "foo.js";
+
+function run_test() {
+  initTestDebuggerServer();
+  const debuggee = addTestGlobal("test-symbols");
+  const client = new DebuggerClient(DebuggerServer.connectPipe());
+
+  client.connect(function() {
+    attachTestTabAndResume(client, "test-symbols", function(response, tabClient, threadClient) {
+      add_task(testSymbols.bind(null, client, debuggee));
+      run_next_test();
+    });
+  });
+
+  do_test_pending();
+}
+
+function* testSymbols(client, debuggee) {
+  const evalCode = () => {
+    Components.utils.evalInSandbox(
+      "(" + function () {
+        var symbolWithName = Symbol("Chris");
+        var symbolWithoutName = Symbol();
+        var iteratorSymbol = Symbol.iterator;
+        debugger;
+      } + "())",
+      debuggee,
+      "1.8",
+      URL,
+      1
+    );
+  };
+
+  const packet = yield executeOnNextTickAndWaitForPause(evalCode, client);
+  const {
+    symbolWithName,
+    symbolWithoutName,
+    iteratorSymbol
+  } = packet.frame.environment.bindings.variables;
+
+  equal(symbolWithName.value.type, "symbol");
+  equal(symbolWithName.value.name, "Chris");
+
+  equal(symbolWithoutName.value.type, "symbol");
+  ok(!("name" in symbolWithoutName.value));
+
+  equal(iteratorSymbol.value.type, "symbol");
+  equal(iteratorSymbol.value.name, "Symbol.iterator");
+
+  finishClient(client);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/unit/test_symbols-02.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that we don't run debuggee code when getting symbol names.
+ */
+
+const URL = "foo.js";
+
+function run_test() {
+  initTestDebuggerServer();
+  const debuggee = addTestGlobal("test-symbols");
+  const client = new DebuggerClient(DebuggerServer.connectPipe());
+
+  client.connect(function() {
+    attachTestTabAndResume(client, "test-symbols", function(response, tabClient, threadClient) {
+      add_task(testSymbols.bind(null, client, debuggee));
+      run_next_test();
+    });
+  });
+
+  do_test_pending();
+}
+
+function* testSymbols(client, debuggee) {
+  const evalCode = () => {
+    Components.utils.evalInSandbox(
+      "(" + function () {
+        Symbol.prototype.toString = () => {
+          throw new Error("lololol");
+        };
+        var sym = Symbol("le troll");
+        debugger;
+      } + "())",
+      debuggee,
+      "1.8",
+      URL,
+      1
+    );
+  };
+
+  const packet = yield executeOnNextTickAndWaitForPause(evalCode, client);
+  const { sym } = packet.frame.environment.bindings.variables;
+
+  equal(sym.value.type, "symbol");
+  equal(sym.value.name, "le troll");
+
+  finishClient(client);
+}
--- a/toolkit/devtools/server/tests/unit/xpcshell.ini
+++ b/toolkit/devtools/server/tests/unit/xpcshell.ini
@@ -200,8 +200,10 @@ reason = bug 820380
 [test_ignore_caught_exceptions.js]
 [test_requestTypes.js]
 reason = bug 937197
 [test_layout-reflows-observer.js]
 [test_protocolSpec.js]
 [test_registerClient.js]
 [test_client_request.js]
 [test_monitor_actor.js]
+[test_symbols-01.js]
+[test_symbols-02.js]