Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 24 Jan 2014 13:36:47 +0100
changeset 181072 3cf6fcb75118778672743cb68ca2dee6890d20d4
parent 181071 55cea8e4946ecdfad2ccb3f0231ef5e206c6fa2a (current diff)
parent 181051 bfe4ed6d47cec0efbc671cf48175e3a36b012b11 (diff)
child 181073 96f5df57e9b797c35e2cc1fc27ab67e506022123
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.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 mozilla-central to mozilla-inbound
browser/devtools/webconsole/hudservice.js
browser/devtools/webconsole/panel.js
browser/devtools/webconsole/test/browser_console_dead_objects.js
browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js
browser/devtools/webconsole/test/head.js
browser/devtools/webconsole/webconsole.js
browser/extensions/pdfjs/content/build/pdf.worker.js
mobile/android/base/resources/drawable-hdpi/copy.png
mobile/android/base/resources/drawable-hdpi/cut.png
mobile/android/base/resources/drawable-hdpi/paste.png
mobile/android/base/resources/drawable-hdpi/select_all.png
mobile/android/base/resources/drawable-mdpi/copy.png
mobile/android/base/resources/drawable-mdpi/cut.png
mobile/android/base/resources/drawable-mdpi/paste.png
mobile/android/base/resources/drawable-mdpi/select_all.png
mobile/android/base/resources/drawable-xhdpi/copy.png
mobile/android/base/resources/drawable-xhdpi/cut.png
mobile/android/base/resources/drawable-xhdpi/paste.png
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- 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
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "9506ca996d28109df7dc8db6e381f54a83aa20ff", 
+    "revision": "5116c92a2905f6646d7049ddd1e1ab68eeb278d9", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- 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
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <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/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="48637bedf20a7d1b8cc3f1638e72eeb44728f467"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <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-feeds.js
+++ b/browser/base/content/browser-feeds.js
@@ -29,18 +29,22 @@ var FeedHandler = {
       // set (because it thinks it's already open).  onpopupshowing gets
       // called after the attribute is unset, and it doesn't get unset
       // if we return false.  so we unset it here; otherwise, the menu
       // refuses to work past this point.
       container.parentNode.removeAttribute("open");
       return false;
     }
 
-    while (container.firstChild)
-      container.removeChild(container.firstChild);
+    for (let i = container.childNodes.length - 1; i >= 0; --i) {
+      let node = container.childNodes[i];
+      if (isSubview && node.localName == "label")
+        continue;
+      container.removeChild(node);
+    }
 
     if (!feeds || feeds.length <= 1)
       return false;
 
     // Build the menu showing the available feed choices for viewing.
     var itemNodeType = isSubview ? "toolbarbutton" : "menuitem";
     for (let feedInfo of feeds) {
       var item = document.createElement(itemNodeType);
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -278,17 +278,23 @@ let gSyncUI = {
    *          "reset" -- reset sync
    */
 
   openSetup: function SUI_openSetup(wizardType) {
     let xps = Components.classes["@mozilla.org/weave/service;1"]
                                 .getService(Components.interfaces.nsISupports)
                                 .wrappedJSObject;
     if (xps.fxAccountsEnabled) {
-      switchToTabHavingURI("about:accounts", true);
+      fxAccounts.getSignedInUser().then(userData => {
+        if (userData) {
+          this.openPrefs();
+        } else {
+          switchToTabHavingURI("about:accounts", true);
+        }
+      });
     } else {
       let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
       if (win)
         win.focus();
       else {
         window.openDialog("chrome://browser/content/sync/setup.xul",
                           "weaveSetup", "centerscreen,chrome,resizable=no",
                           wizardType);
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -118,17 +118,19 @@
                    tooltip="bhTooltip">
         <!-- bookmarks menu items -->
       </toolbaritem>
 
     </panelview>
 
     <panelview id="PanelUI-socialapi" flex="1"/>
 
-    <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);"></panelview>
+    <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
+      <label value="&feedsMenu.label;" class="panel-subview-header"/>
+    </panelview>
 
     <panelview id="PanelUI-helpView" flex="1">
       <label value="&helpMenu.label;" class="panel-subview-header"/>
       <vbox id="PanelUI-helpItems"/>
     </panelview>
 
     <panelview id="PanelUI-developer" flex="1">
       <label value="&webDeveloperMenu.label;" class="panel-subview-header"/>
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -79,40 +79,39 @@
         // Make sure we rebuild the popup in onpopupshowing
         this._needToBuildPopup = true;
 
         var os =
                Components.classes["@mozilla.org/observer-service;1"]
                          .getService(Components.interfaces.nsIObserverService);
         os.addObserver(this, "browser-search-engine-modified", false);
 
-        this._addedObserver = true;
+        this._initialized = true;
 
         this.searchService.init((function search_init_cb(aStatus) {
           // Bail out if the binding's been destroyed
-          if (this._destroyed)
+          if (!this._initialized)
             return;
 
           if (Components.isSuccessCode(aStatus)) {
             // Refresh the display (updating icon, etc)
             this.updateDisplay();
           } else {
             Components.utils.reportError("Cannot initialize search service, bailing out: " + aStatus);
           }
         }).bind(this));
       ]]></constructor>
 
       <destructor><![CDATA[
-        this._destroyed = true;
+        if (this._initialized) {
+          this._initialized = false;
 
-        if (this._addedObserver) {
           var os = Components.classes["@mozilla.org/observer-service;1"]
                              .getService(Components.interfaces.nsIObserverService);
           os.removeObserver(this, "browser-search-engine-modified");
-          this._addedObserver = false;
         }
 
         // Make sure to break the cycle from _textbox to us. Otherwise we leak
         // the world. But make sure it's actually pointing to us.
         if (this._textbox.mController.input == this)
           this._textbox.mController.input = null;
       ]]></destructor>
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -124,16 +124,17 @@ These should match what Safari and other
 <!ENTITY shareLinkCmd.label "Share This Link">
 <!ENTITY shareLinkCmd.accesskey "s">
 <!ENTITY shareImageCmd.label "Share This Image">
 <!ENTITY shareImageCmd.accesskey "s">
 <!ENTITY shareSelectCmd.label "Share Selection">
 <!ENTITY shareSelectCmd.accesskey "s">
 <!ENTITY shareVideoCmd.label "Share This Video">
 <!ENTITY shareVideoCmd.accesskey "s">
+<!ENTITY feedsMenu.label "Subscribe">
 <!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
 <!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
 <!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">
 <!ENTITY showAllBookmarks2.label "Show All Bookmarks">
 <!ENTITY unsortedBookmarksCmd.label "Unsorted Bookmarks">
 <!ENTITY bookmarksToolbarChevron.tooltip "Show more bookmarks">
 
 <!ENTITY backCmd.label                "Back">
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -156,21 +156,16 @@ var BrowserUI = {
         FindHelperUI.init();
 #ifdef NIGHTLY_BUILD
         PdfJs.init();
 #endif
       } catch(ex) {
         Util.dumpLn("Exception in delay load module:", ex.message);
       }
 
-      if (WindowsPrefSync) {
-        // Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
-        WindowsPrefSync.init();
-      }
-
       // check for left over crash reports and submit them if found.
       BrowserUI.startupCrashCheck();
 
       Util.dumpLn("* delay load complete.");
     }, false);
 
 #ifndef MOZ_OFFICIAL_BRANDING
     setTimeout(function() {
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -180,18 +180,17 @@ var Browser = {
           let uri = commandURL || Browser.getHomePage();
           self.addTab(uri, true);
         }
       }
 
       // Should we restore the previous session (crash or some other event)
       let ss = Cc["@mozilla.org/browser/sessionstore;1"]
                .getService(Ci.nsISessionStore);
-      let shouldRestore = ss.shouldRestore()
-                       || (3 == Services.prefs.getIntPref("browser.startup.page"));
+      let shouldRestore = ss.shouldRestore();
       if (shouldRestore) {
         let bringFront = false;
         // First open any commandline URLs, except the homepage
         if (activationURI && activationURI != kStartURI) {
           this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP });
         } else if (commandURL && commandURL != kStartURI) {
           this.addTab(commandURL, true);
         } else {
--- a/browser/metro/components/SessionStore.js
+++ b/browser/metro/components/SessionStore.js
@@ -4,16 +4,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
 
 #ifdef MOZ_CRASHREPORTER
 XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
   "@mozilla.org/xre/app-info;1", "nsICrashReporter");
 #endif
 
 XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
   "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
@@ -194,16 +195,20 @@ SessionStore.prototype = {
         observerService.addObserver(this, "browser-lastwindow-close-granted", true);
         observerService.addObserver(this, "browser:purge-session-history", true);
         observerService.addObserver(this, "quit-application-requested", true);
         observerService.addObserver(this, "quit-application-granted", true);
         observerService.addObserver(this, "quit-application", true);
         break;
       case "final-ui-startup":
         observerService.removeObserver(this, "final-ui-startup");
+        if (WindowsPrefSync) {
+          // Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
+          WindowsPrefSync.init();
+        }
         this.init();
         break;
       case "domwindowopened":
         let window = aSubject;
         window.addEventListener("load", function() {
           self.onWindowOpen(window);
           window.removeEventListener("load", arguments.callee, false);
         }, false);
@@ -335,19 +340,22 @@ SessionStore.prototype = {
     this._windows[aWindow.__SSID] = { tabs: [], selected: 0, _closedTabs: [] };
 
     // Perform additional initialization when the first window is loading
     if (this._loadState == STATE_STOPPED) {
       this._loadState = STATE_RUNNING;
       this._lastSaveTime = Date.now();
 
       // Nothing to restore, notify observers things are complete
-      if (!this._shouldRestore) {
+      if (!this.shouldRestore()) {
         this._clearCache();
         Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
+
+        // If nothing is being restored, we only have our single Metro window.
+        this._orderedWindows.push(aWindow.__SSID);
       }
     }
 
     // Add tab change listeners to all already existing tabs
     let tabs = aWindow.Browser.tabs;
     for (let i = 0; i < tabs.length; i++)
       this.onTabAdd(aWindow, tabs[i].browser, true);
 
@@ -721,17 +729,17 @@ SessionStore.prototype = {
     let browser = aTab.linkedBrowser;
     if (browser.__SS_extdata && browser.__SS_extdata[aKey])
       delete browser.__SS_extdata[aKey];
     else
       throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
   },
 
   shouldRestore: function ss_shouldRestore() {
-    return this._shouldRestore;
+    return this._shouldRestore || (3 == Services.prefs.getIntPref("browser.startup.page"));
   },
 
   restoreLastSession: function ss_restoreLastSession(aBringToFront) {
     let self = this;
     function notifyObservers(aMessage) {
       self._clearCache();
       Services.obs.notifyObservers(null, "sessionstore-windows-restored", aMessage || "");
     }
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -963,16 +963,40 @@ nsGonkCameraControl::SetPictureSize(uint
     RwAutoLockWrite write(mRwLock);
     mParams.setPictureSize(static_cast<int>(w), static_cast<int>(h));
   }
 
   // Finally, update the thumbnail size
   UpdateThumbnailSize();
 }
 
+int32_t
+nsGonkCameraControl::RationalizeRotation(int32_t aRotation)
+{
+  int32_t r = aRotation;
+
+  // The result of this operation is an angle from 0..270 degrees,
+  // in steps of 90 degrees. Angles are rounded to the nearest
+  // magnitude, so 45 will be rounded to 90, and -45 will be rounded
+  // to -90 (not 0).
+  if (r >= 0) {
+    r += 45;
+  } else {
+    r -= 45;
+  }
+  r /= 90;
+  r %= 4;
+  r *= 90;
+  if (r < 0) {
+    r += 360;
+  }
+
+  return r;
+}
+
 nsresult
 nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
 {
   if (aTakePicture->mCancel) {
     if (mCameraHw.get()) {
       mCameraHw->CancelTakePicture();
     }
   }
@@ -986,23 +1010,20 @@ nsGonkCameraControl::TakePictureImpl(Tak
   mDeferConfigUpdate = true;
 
   SetPictureSize(aTakePicture->mSize.width, aTakePicture->mSize.height);
 
   // Picture format -- need to keep it for the callback.
   mFileFormat = aTakePicture->mFileFormat;
   SetParameter(CameraParameters::KEY_PICTURE_FORMAT, NS_ConvertUTF16toUTF8(mFileFormat).get());
 
-  // Convert 'rotation' to a positive value from 0..270 degrees, in steps of 90.
-  uint32_t r = static_cast<uint32_t>(aTakePicture->mRotation);
+  // Round 'rotation' up to a positive value from 0..270 degrees, in steps of 90.
+  int32_t r = static_cast<uint32_t>(aTakePicture->mRotation);
   r += mCameraHw->GetSensorOrientation(GonkCameraHardware::OFFSET_SENSOR_ORIENTATION);
-  r %= 360;
-  r += 45;
-  r /= 90;
-  r *= 90;
+  r = RationalizeRotation(r);
   DOM_CAMERA_LOGI("setting picture rotation to %d degrees (mapped from %d)\n", r, aTakePicture->mRotation);
   SetParameter(CameraParameters::KEY_ROTATION, nsPrintfCString("%u", r).get());
 
   // Add any specified positional information -- don't care if these fail.
   if (!isnan(aTakePicture->mPosition.latitude)) {
     DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aTakePicture->mPosition.latitude);
     SetParameter(CameraParameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aTakePicture->mPosition.latitude).get());
   }
@@ -1512,24 +1533,17 @@ nsGonkCameraControl::SetupRecording(int 
     aMaxFileSizeBytes = -1;
   }
   snprintf(buffer, SIZE, "max-filesize=%lld", aMaxFileSizeBytes);
   CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
 
   // adjust rotation by camera sensor offset
   int r = aRotation;
   r += mCameraHw->GetSensorOrientation();
-  r %= 360;
-  r += 45;
-  r /= 90;
-  r *= 90;
-  if (r < 0) {
-    // the video recorder only supports positive rotations
-    r += 360;
-  }
+  r = RationalizeRotation(r);
   DOM_CAMERA_LOGI("setting video rotation to %d degrees (mapped from %d)\n", r, aRotation);
   snprintf(buffer, SIZE, "video-param-rotation-angle-degrees=%d", r);
   CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
 
   CHECK_SETARG(mRecorder->setListener(new GonkRecorderListener(this)));
 
   // recording API needs file descriptor of output file
   CHECK_SETARG(mRecorder->setOutputFile(aFd, 0, 0));
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -91,16 +91,18 @@ protected:
 
   nsresult SetupRecording(int aFd, int aRotation, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs);
   nsresult SetupVideoMode(const nsAString& aProfile);
   void SetPreviewSize(uint32_t aWidth, uint32_t aHeight);
   void SetThumbnailSize(uint32_t aWidth, uint32_t aHeight);
   void UpdateThumbnailSize();
   void SetPictureSize(uint32_t aWidth, uint32_t aHeight);
 
+  int32_t RationalizeRotation(int32_t aRotation);
+
   android::sp<android::GonkCameraHardware> mCameraHw;
   double                    mExposureCompensationMin;
   double                    mExposureCompensationStep;
   bool                      mDeferConfigUpdate;
   PRRWLock*                 mRwLock;
   android::CameraParameters mParams;
   uint32_t                  mWidth;
   uint32_t                  mHeight;
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -813,16 +813,16 @@ pref("browser.snippets.updateInterval", 
 
 // URL used to check for user's country code
 pref("browser.snippets.geoUrl", "https://geo.mozilla.org/country.json");
 
 // URL used to ping metrics with stats about which snippets have been shown
 pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
 
 // These prefs require a restart to take effect.
-pref("browser.snippets.enabled", false);
+pref("browser.snippets.enabled", true);
 pref("browser.snippets.syncPromo.enabled", false);
 
 #ifdef MOZ_ANDROID_SYNTHAPKS
 // The URL of the APK factory from which we obtain APKs for webapps.
 // This currently points to the development server.
 pref("browser.webapps.apkFactoryUrl", "http://dapk.net/application.apk");
 #endif
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -711,16 +711,18 @@ public abstract class GeckoApp
                 handlersJSON.put("apps", new JSONArray(appList));
                 mCurrentResponse = handlersJSON.toString();
             } else if (event.equals("Intent:Open")) {
                 GeckoAppShell.openUriExternal(message.optString("url"),
                     message.optString("mime"), message.optString("packageName"),
                     message.optString("className"), message.optString("action"), message.optString("title"));
             } else if (event.equals("Locale:Set")) {
                 setLocale(message.getString("locale"));
+            } else if (event.equals("SystemUI:Visibility")) {
+                setSystemUiVisible(message.getBoolean("visible"));
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     public String getResponse(JSONObject origMessage) {
         String res = mCurrentResponse;
@@ -1575,16 +1577,17 @@ public abstract class GeckoApp
         registerEventListener("Update:Check");
         registerEventListener("Update:Download");
         registerEventListener("Update:Install");
         registerEventListener("PrivateBrowsing:Data");
         registerEventListener("Contact:Add");
         registerEventListener("Intent:Open");
         registerEventListener("Intent:GetHandlers");
         registerEventListener("Locale:Set");
+        registerEventListener("SystemUI:Visibility");
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
         }
 
         mContactService = new ContactService(GeckoAppShell.getEventDispatcher(), this);
 
         mPromptService = new PromptService(this);
@@ -2104,16 +2107,17 @@ public abstract class GeckoApp
         unregisterEventListener("Update:Check");
         unregisterEventListener("Update:Download");
         unregisterEventListener("Update:Install");
         unregisterEventListener("PrivateBrowsing:Data");
         unregisterEventListener("Contact:Add");
         unregisterEventListener("Intent:Open");
         unregisterEventListener("Intent:GetHandlers");
         unregisterEventListener("Locale:Set");
+        unregisterEventListener("SystemUI:Visibility");
 
         deleteTempFiles();
 
         if (mLayerView != null)
             mLayerView.destroy();
         if (mDoorHangerPopup != null)
             mDoorHangerPopup.destroy();
         if (mFormAssistPopup != null)
@@ -2810,9 +2814,22 @@ public abstract class GeckoApp
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GeckoApp.this.doRestart();
                 GeckoApp.this.finish();
             }
         });
     }
+
+    private void setSystemUiVisible(final boolean visible) {
+        ThreadUtils.postToUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (visible) {
+                    mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+                } else {
+                    mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
+                }
+            }
+        });
+    }
 }
--- a/mobile/android/base/home/HomeConfig.java
+++ b/mobile/android/base/home/HomeConfig.java
@@ -163,18 +163,21 @@ public final class HomeConfig {
 
         public PanelConfig(PanelConfig panelConfig) {
             mType = panelConfig.mType;
             mTitle = panelConfig.mTitle;
             mId = panelConfig.mId;
             mLayoutType = panelConfig.mLayoutType;
 
             mViews = new ArrayList<ViewConfig>();
-            for (ViewConfig viewConfig : panelConfig.mViews) {
-                mViews.add(new ViewConfig(viewConfig));
+            List<ViewConfig> viewConfigs = panelConfig.mViews;
+            if (viewConfigs != null) {
+                for (ViewConfig viewConfig : viewConfigs) {
+                    mViews.add(new ViewConfig(viewConfig));
+                }
             }
             mFlags = panelConfig.mFlags.clone();
 
             validate();
         }
 
         public PanelConfig(PanelType type, String title, String id) {
             this(type, title, id, EnumSet.noneOf(Flags.class));
--- a/mobile/android/base/preferences/CustomListPreference.java
+++ b/mobile/android/base/preferences/CustomListPreference.java
@@ -75,18 +75,22 @@ public abstract class CustomListPreferen
     }
 
     /**
      * Returns the Android resource id for the layout.
      */
     protected abstract int getPreferenceLayoutResource();
 
     /**
-     * Set whether this object's UI should display this as the default item. To ensure proper ordering,
-     * this method should only be called after this Preference is added to the PreferenceCategory.
+     * Set whether this object's UI should display this as the default item.
+     * Note: This must be called from the UI thread because it touches the view hierarchy.
+     *
+     * To ensure proper ordering, this method should only be called after this Preference
+     * is added to the PreferenceCategory.
+     *
      * @param isDefault Flag indicating if this represents the default list item.
      */
     public void setIsDefault(boolean isDefault) {
         mIsDefault = isDefault;
         if (isDefault) {
             setOrder(0);
             setSummary(LABEL_IS_DEFAULT);
         } else {
--- a/mobile/android/base/preferences/SearchPreferenceCategory.java
+++ b/mobile/android/base/preferences/SearchPreferenceCategory.java
@@ -11,16 +11,17 @@ import android.util.Log;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.util.GeckoEventListener;
+import org.mozilla.gecko.util.ThreadUtils;
 
 public class SearchPreferenceCategory extends CustomListCategory implements GeckoEventListener {
     public static final String LOGTAG = "SearchPrefCategory";
 
     public SearchPreferenceCategory(Context context) {
         super(context);
     }
 
@@ -76,17 +77,17 @@ public class SearchPreferenceCategory ex
             this.removeAll();
 
             // Create an element in this PreferenceCategory for each engine.
             for (int i = 0; i < engines.length(); i++) {
                 try {
                     JSONObject engineJSON = engines.getJSONObject(i);
                     final String engineName = engineJSON.getString("name");
 
-                    SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
+                    final SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
                     enginePreference.setSearchEngineFromJSON(engineJSON);
                     enginePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                         @Override
                         public boolean onPreferenceClick(Preference preference) {
                             SearchEnginePreference sPref = (SearchEnginePreference) preference;
                             // Display the configuration dialog associated with the tapped engine.
                             sPref.showDialog();
                             return true;
@@ -95,17 +96,22 @@ public class SearchPreferenceCategory ex
 
                     addPreference(enginePreference);
 
                     // The first element in the array is the default engine.
                     if (i == 0) {
                         // We set this here, not in setSearchEngineFromJSON, because it allows us to
                         // keep a reference  to the default engine to use when the AlertDialog
                         // callbacks are used.
-                        enginePreference.setIsDefault(true);
+                        ThreadUtils.postToUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+                                enginePreference.setIsDefault(true);
+                            }
+                        });
                         mDefaultReference = enginePreference;
                     }
                 } catch (JSONException e) {
                     Log.e(LOGTAG, "JSONException parsing engine at index " + i, e);
                 }
             }
         }
     }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d8069cf7e05fb22792d5fa586999b87723c014df
GIT binary patch
literal 797
zc$@(p1LFLNP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0008yNkl<Zc-rlm
z%}Z2a6vjhBBqT({2oY)Hs+}z)T;$l?x%26Kxd@CPS_D!Qv<U(iE)o@y7NVF^ArVRt
zR)P=&X|;%=^5fr`o+sWz7vWChy?N%E@8aN{J9plBe&?L`ob!$+DwWESHVa?@4g=uA
z#aJLq=7vrsGNl`rllf<{L~g6!$!^1b;`$Try>!yWyUAR+^MLCfIsk<?IGN(@{zUG}
zB`3RA%?K1v6{hi-wkQBld<(q0>Jj)I0v8a8>u$C@0PDl`P&{3jL?k}SbBqe!>!~LI
z#WxSQgX>1rE`&eAz4j{4pG;(mHwnqlAY$JLQ8xexo;P0KhL?wH2QQzOXvEyXO@N(N
z2Y~0|^g2brt0Qv%AP^D>q}RAQfaE<=Xf0^fLRGpi`-V|a17M#2@qQ^EqU<(Pyjkap
z8UVhm?D1S<Kmdv4bFPK`G^+)`(BCr~@I7CLG35Wm?^I0YUugn7F!{e85`b%snzi02
zrcm*gX+~RN0gyT~TnnkRq6WYcD$Pq8S5SlJUrQ;~tU`_KqWogaKz9O)rz5(hnz`9h
zO0^GgwlQh+nKe961xn?YJl(iK6M&txL!tm7Penkj#<5!lJ6vDW?!;0-#wb7_YK;WX
z1?V9=X7er!yz(qma;1xkAr(Hrn^!q?`s94Ccl724W;fQFMkzWCOL2UF_#Yl28(tWs
z)>nF#2Nx$@c!<A`nde?uo*8(8Q#lVX#GLiL0>mKn1>SGMp6J3ea{}gP^g5j2XdNj<
z{H%}oWs2YTd@E02#`6oTG>ilfGJrfM&#3?~mnp)}n;eG&2+{$dczEwgwR8a7R3rhI
z7EBL6;WCLLCC-KwC+q!F0M_)sY{YjEe};=k62PyLNXeAnbRrADQ<9JPx2!T;G|~Vp
zcO268iC>dZA?g4!taV{8Eb`|<ZfI%wM+HF3q7NV<!<Yp)_9<imEPw^D0QMi<7Qh1h
buK>RQCoN`p4?r0F00000NkvXXu0mjf;rL`!
rename from mobile/android/base/resources/drawable-hdpi/copy.png
rename to mobile/android/base/resources/drawable-hdpi/ab_copy.png
index 0dd8865f4a9aefc688496d3f3da1a3a131adf40c..0c8933e5db60945b72443a15206b0e7e2fc53cbc
GIT binary patch
literal 193
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt4o?@ykcwMxZ|d?j81Ohel;vt=
zVhJuNmAS52wCp6)%S#t+KYsbN^tYh5(x=xT%}fb5`*){a-lM9@aFHR^u=`p~9D@u)
zR$RlgbY_PVhsm26L54g0ElXlzh|6DC<->5GUH1qJ!-ols5}y>cBmEd0N*Z<vFfh0=
lyk_{q@?bJQQ2pQU3><I8Cr!Uu^8m<W@O1TaS?83{1OODDL0kX;
rename from mobile/android/base/resources/drawable-hdpi/cut.png
rename to mobile/android/base/resources/drawable-hdpi/ab_cut.png
index c760936ee152c1e85e625404b32fcdb1e634f079..9cabe022de057bba4c2901f8d32118b65823a38a
GIT binary patch
literal 664
zc$@*40%!e+P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0007CNkl<Zc-rk*
zJxc>Y5KUnbQlv;>V<}kJDhO%Rd|bZ2V`C>+2!dcE2!fqhS=dMjf{0ky2tfoTq_C2R
zBq;iK;yiN$%dw|PaFbivVn}YY+{~MOGxP4^>-BnCn*m?|7y$njz>1ao9G5MIBfekE
z0MHizJNRoe01N<y0Ft@t99cM(UkhplfC8S1r%QG5w|J&>jCCylQ1GX?UbS-FSgLr7
zPh4A>@{#8NNN5vffAoE+zgAiP29(G@s{{b&^K{J9BL)xZ_@l`}%g+8gxZhu|&e&^j
zDgeN7fE+)tlUTZVj!X^<fGBb(`lEY3TG{dr-<#-kqXdARrCD-t=?I{O00>}ckkdof
zWfPj|gRZ2y2EbQ~X#nG5q{2KyOLU_SXPJ#p6IrK|+2<rE2f%HRobFQAI?kXFXd+wQ
z0`252llN5C0c@g!3<ZtMyHKKoc1an&5;G3Ud2SM;9a2{BB_LizK-lMLDM7T@q(Ixa
z7ifbu(8(TBd!E)p;5z8Rb%BoM0C3=00GJ6xp{A@3ME+yqdI|t0C=Im>mm+>88lCX(
zJbgi>i333UL+?iam$cD4)B^Sh;;rV`)1*Bc+-gM|#~>?2l7%N(%Ool-xYY**-H@Er
z2h=De23oRG02uS+?Aobi?4cDLP)c-vkP>ZWQUU>@&kM4l#<F1;1OG*TNC+ih8?;j{
z=2+0NW*NblN=-pdhj^lMa<qJ)!5S-4T^=dxJR2bF@QG^_vn~(y0dYR?^RRZWRZvs*
yYZbqFv1I_bn0dW!0E`!a`IpiFFaQhykJ=ZJxhh70199H~0000<MNUMnLSTXrLLnjm
index ed03f620f8ef9e969d0471ab76329038e25c9f0d..ee614d589e5dcf07bd21e43f7ade7d3383f95c24
GIT binary patch
literal 574
zc$@(~0>S->P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm00067Nkl<Zc-rll
z-AV#M7=|Mjk?5d<=%m}|NTN{D-P~5wRXU6=rL!n0$>@jfBZz*~ETgNkZ)k?z2G@a|
zrJapAc-dtgndjNr`M%YK>2#XuSOF_w1+0J-umb;2V53k<Jv;TzBE^xe8!mwG6mgy@
zfgkYpx)+3grd9y%`f{b#yeql&4|g{_G*3Vce@pNa%3IlMJkYf@F~&pzgkK`~8+PYQ
zUSmY?k6zF&;23iR)bLLPzlmc^6OiGr0sfibxA<p{iF*Ly^8|mz;fLSw;Wol+2&4~h
zngGJ*2>ue_U+A$ZBD}r;PMSP?UxF_qyp{llO$x`P;4cI`WkB#1K8K^=i6=l=73Z4p
z4#D?+!-v&4@FL1PPpy29miV46v6x5${v6<k1n(hyoXmx1wV1VY$~&tNxXEI`pGojF
zgil<6A6IyTnM70y<twp1y#5}@L%CB|41}l9ce?;TB6uI+b)($CC?Qu4ArT4hH%}$_
z0O6AtP)qdX3IY-`{0SdB;P4GG_OE}`qXgD)St2JkEx{iH{41+u2%oe-9EqO1Da8uR
zfN$X{r6vH4EK0(w`mLjR@Tm!4<i-TRV+PHI#suF+cvA!-yDMvS0N+7)(*$Nobc=5N
zlRq~52ydc5qy)hqAiU86D1i}DnGnDz;6?1e(^kL=SOF_w1*`z(3;Z`mn%T!Z5C8xG
M07*qoM6N<$f?A^jEdT%j
rename from mobile/android/base/resources/drawable-hdpi/paste.png
rename to mobile/android/base/resources/drawable-hdpi/ab_paste.png
index 886c49317e0b1477bfdc4a4b7601d6caf8649198..0be696557481d253ea906e6b6eb0a33b68ab859b
GIT binary patch
literal 324
zc$@)50lWT*P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0003CNkl<Zc-rlm
zy$ZrG6h<9=ADx`6ZPPzfTdSk9Zz9e<fwLgE`UawdgW&7bUQh}`p=l!5z&9MY4JG8{
zerciYm1Su)5U@gEIGQLCrOUoZ<{KwSF9g*zrZ^9ufS=^sv5-$M%8mrpG-i!Jwd*%8
z&i0>cs%eZ(fOb%oZ-FjzunN2*bRei^7cd0BKvP~rxfrxv7~R`650gOs<Y|K+=exfV
z2xTGMaCTOWhZCgNU|Os>1!(cHBjiIT=as~YO~8$^lkP#K?y(7I?S37lJA;5(AOHbd
z1yl|yIsk#j2<d|kAVLbD0}$vCA#?x&KYWp)0}y}!1R!7(d|rouLGYg#0uX?}|MLQS
WL1h)ZtVA9F0000<MNUMnLSTYr2Y+(_
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..10a4b7432e1001b82afd43aca0b02b51dc41f74d
GIT binary patch
literal 846
zc$@)F1F`&xP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0009ONkl<Zc-rlm
z%}Z2a6vkr+krp8#Nvl?Yh`4g)!kV$UbLaa*#eJJ1m$gX<i55XEk`fV$Xdx<yMPQ5k
zMy*Xyl-9p9JrB&u!=;$H&U?lY?&5{vdhdPD@0|0TbKdK@YPEW%R|F6NL;!&cgF}h`
zu5@8M=I6)a$!z)Ah+kYwqza$oUjAo1Rrr?hi@P_|r4=t*nMxPNuJL{c%N;-}H#!cZ
zH*a|P-wmu^fLR1c|7ioz>)kMBA!sB$53lcxq)Q)a(Kw*tfqM=Skq3<2sQ|!(SD6~x
zD8Rh)^P@!=)%g$D%c)#t63^`GXOfxnYy9neD*<TCC3tpQjDUx~z;M6LhVpC&Jb#~2
zQV_E(1z--#<^WkoG<w2rPQgRq-{n2f(QRu05$uHaJdD3`(i}$AvZ4)EE56GVfP$kq
zrJBHt$!04F%I;Hf2!C4w&|}w?V3(UTUNq4~@7JR6m4Y?{V3SfgJK?G!LB#X&UPjdn
z0D}D}bsnC&=n6pV3Ki<18303Et2`U7jF+CGO6n^!0I3+9Yg_^_@0GTe%mAeMV3YTb
z0XqKzWJ+(%09g0A2}<dnO8^MBPo>avGXSQJ^Z@3qLlNISu5Oh(W&oTX)kc%90N7Jh
z8SOO#;9*3B%#KX)IjBJW@=jE@E%RAO4{~0va<578#yEoOfzBF$9veV4I+BKlkPn{_
zfGIhxrrIq=)EYoGp5mr5MPf$Eg!Me$@kk$RIGMKcKodi~exuL1oFqAzHBvH>Hmllr
z(Ukc(9qgVmgz0GD+6&}ziGs&H7YN0)!?jziHu`KF0>bXA1nahp!(kSWq)Zzc9fW`r
z<~VP$sj*920*J7CylnXihrI?2|HNpBVCiuU5nTN0K?qX-omTLw$B~#{8@M@V8~mPO
zq?rG~XTm_30609<yri-9AlepyUpHuI2#B_ez)T$g4bjnd0Q4-!lrRv60QL|(dO83w
zgIK5oz&Y%PA%HyuMQ;dT55Z3{MgaB@Xq1l)s*oK71<Rag+Ndvr(SIo;fCwN0hyZNY
YA00i7^RVudCjbBd07*qoM6N<$f^;x~dH?_b
rename from mobile/android/base/resources/drawable-hdpi/select_all.png
rename to mobile/android/base/resources/drawable-hdpi/ab_select_all.png
index 902402e26efd69430ebd4ff0d25bf075f475ce73..e7b2b205f3c52212246014c63ba640db68d7e98e
GIT binary patch
literal 199
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtK2I0NkcwMxXYS={FyLwV9pLBp
z=)tqszpXy<Gb#Bw>Z#r@aL%0lDX@=w$;`;>Oh6qB9y|uRugkI|o|k!STgP1>erdJN
zfydsgpT6&AKENDmQ}DK4v*26la-9ZoA;uk-m>)3O2(T!yzi55YdV;a2LFNE+g#v>E
s-v#cA+z%VCFq~n3!f@sU$XtfH%X|!ldkeIr#14YEp00i_>zopr005#z?f?J)
index bb6aef1d069a14a7fc1cea9780c919c61679e4fa..6744de04390f846457972a4c699f2e0f9be5a33c
GIT binary patch
literal 144
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezt=sPZ!6Kid%1QEaYWS;Bj?qb5i7F
zJKo0=WwzpwgWn!Tzdt6KogK@W89-pitr^+rj3Cw@-W6+?GcrgRf;bJ{JP8m5_g;gk
Z_so1to1;9Gu6K)qxSp<lF6*2UngHmZB>4aU
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4af976e251efe3f002feea608d7b77d3d750217c
GIT binary patch
literal 569
zc$@(_0>=G`P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800062Nkl<Zc-rlk
zJ4*vW6oo}3h=quVAQo13Vx=Hybo1D3ve~>-SXwFASct8Hf`x@(qk@ePBp^P(2O_=|
z6j2Lbe<z+pW(q^XuI>;mwzy<AOy+#&&b>EDL#b5y)9?UnHw^d#-@>qRL*ZC@Ef7iE
zX}a~MMH0_JBYB{kndxXE-^x8T!W{q(_d$4NM7KU5`iS*9L}zs~y%>z9_Qm@ThLzP-
z15ms%6isbW1fuhJZmE))L1f|_S$V}etP~&;&rCr4Q;%n+YPgf2?ExcsiR-y1q%r^;
zdJA_)T-ycQYlJ1V3IMpu^_36IjynL5z}L94q7ncUl|=wJ^E(BAcmWwZQw3lO0PP0=
zMF5<tx`G}8p!#Q=h_hqZj%d>jWkm=#$1Fq~-fRbeS{V~HlUD}7;lddJSF3bbOPmD@
z_fG&m;XYLWbTx_r^G;{D-)#u>SESv?E`j(<c?RTq-3}ri+KDl{fV-cgdy#=<&VGV$
z;IP;bdlVLMyAbboJ&JKi7u$%3GWey#EC{!47&4QgSZWh{4hax8(@VIfVJYMafDYj9
zN{UMWIa+PP9ROPn;x|%Q23^XcauWQ^uK+kgtBCK|xK{?ie!r*?FUsDp3jpUme{2Zx
zf)uY8fNZ}G4j#NV@wwgrmElOtX}ADTlK~IF1MvPE{!4%_G^x6rv#tJG00000NkvXX
Hu0mjfFwO2P
rename from mobile/android/base/resources/drawable-mdpi/copy.png
rename to mobile/android/base/resources/drawable-mdpi/ab_copy.png
index 74cb920f487b60595b896c04ebc6bdf9dbd746ce..ac097fa93a6caf091945332f94c0ed25230e04d5
GIT binary patch
literal 166
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJTu&FrkcwMxryFt|P~dU34N+Hr
zdExBq?^c3bijuDadjD|MS7cZG2uKnV)DZcx-eKn}+rtyjKe-WffUTBMC&7i=NBw48
zf(0k*G|oMxX-pMN{K5x>K8Uq&X>4fsaGcZdiD#k10jDPM2j@GOY^7F}PDo4_cHalI
On8DN4&t;ucLK6T7&^ZnO
rename from mobile/android/base/resources/drawable-mdpi/cut.png
rename to mobile/android/base/resources/drawable-mdpi/ab_cut.png
index 8e6a93fe4fd079ccc034d09f86ffa37a2e9e2f5e..4314e82d1588aaef6809b2898a5c9924a0354561
GIT binary patch
literal 459
zc$@*t0W|)JP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004!Nkl<Zc-rlk
zze~eF6vsO_h=YTJARQbE{sTG%2ODjYrcKhO&7j~QI0){7|9}V%g1CsdiHM_!Lvaus
zEQ$yg{deN`i+2(*L)-jlg&Q8Z>s{aby!*a;O$%Wdj?@&u_yMdK&Q}_?r0Ini`$qs`
z&MysQ3Sg`Ns&0FJ)$(pR$MfED+FHf{(il9LM9_|Ic~6$p@(6<Q<In)0UpDLhF0v~1
z17Otr1NvF3Hm(U%v75(b(|sEnz^u2{nE}_B%@0g46BisA+t~LRy_RLe>A}ZlA_)+1
z0)cmsNmn@iK!%ra>~l@%Uc&n8@4DT%!1@+GpG&I<2{MHv-bbK!xt~FC%qP0(K68%o
z8G~ke3n)RQ);waS0C?f)5P*8iJ$V2e3V?0|;5<tJDZw7ATJGl<fls9b)ILsvw2QEZ
zBD_M81(6~wQjVA+EG7bgla0tVyc5@Ow%=>WIecs<X+#=>;<+$jBf0_Tv}{Cqx8euU
zif!47bNw;mX;CgI8|I7ZePGl8>aAG)Gg1J5>>Crd|KuZYy@~(;002ovPDHLkV1jr^
B%+3G+
index b28b3b54f4c81d482f797f31936cbd4013c093b5..bc87b16277f14ff00d2c24dd279b6113a795c1ea
GIT binary patch
literal 442
zc$@*c0Y(0aP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004jNkl<Zc-rlj
z%}T>S5XVKNc<|s=iin6$pdj>6Xw|l{rZ)Y!>Dkw?C@NLdhw#u^{CWfLg6$in^KW-x
zVMy1wZ0sS2VL~AD`|a%Pl7%n~|20y9RABxEc5_AR@M`TviY4t`asq%O@SL~+ue##5
zcFM=iQ|AH_j@;Vb_v)X8a_xsi^4t|S0usJO@DIRC)y4(D4m%*>2VVW1;cjO@!Z$T|
zM+~F2fEoU#;Fl6^7MOg%5fi>a@Yg9kxcc)kL_vxbmiZ-oUBQR6@@oM%2`~(q&g?lA
zd%=n{hzUNJ!h;(Dk1KFk4Z4MrKSEIyXIKP03t7PFyW6Pki+u{vMifO`^-j!ycTMnE
zLpVbsqu^`wzOUeS0&Xk75}0O8HI5c87j5Oe3H&IykAhomfnE^jS#@GS_xT>>XUqt}
zAFv$)ZY>}sxD(&S%E=cp!Jl{*1l&Tv)QJwZgW!(>?n;0mDlgL=aYlJnz+DO;7%0HW
k2*?Y_GSc7jRA7Dt#!u1eMKY>%JOBUy07*qoM6N<$f}JkNng9R*
rename from mobile/android/base/resources/drawable-mdpi/paste.png
rename to mobile/android/base/resources/drawable-mdpi/ab_paste.png
index 61fd91c8808a6cc1c8bcae5d7c5db8305c92bd44..f87d274e4c9b124858558ce30764fcef71701935
GIT binary patch
literal 249
zc$@+G00#ewP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80002MNkl<Zc-rlk
zO$x#=5Jp|N@;t6wX|QQcY5F6*N%!Ifyn&~2;X<T4uM=msrEP+I(o$yeAY=ySWrhT@
za?VZ4`~|i<)k~6{jY{$d!)x9f0WY9p`=r7-!)v&}US}U4R9rJ5xflUIc!6#!by{7A
zicsv*&4&q`Y`vxe%^|k0ApwfDEJ(Q<xIkpeTWGtFrntie=ydN;0qz7;;1`xB(AVlQ
zNg2VPN8m?BFv$qy7RW;+0?QLXFna;{8;ZaeTWULgcV@%J00000NkvXXu0mjfRxoB-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..022e173c4a239b83e17f4a5551fe00aec37b67d8
GIT binary patch
literal 587
zc$@)C0<`^!P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80006KNkl<Zc-rlk
z&npCB7{@mU2T78WlcXFZIdGA}F1s`A%&y&aQEm=O<e)^!K{+}ge}bDLxk}{cTKUoX
zch>W%cWP*V&AhX5*u&GzzRmkSpXdAhc-v5+Q20};1N?6Q)1GUJ##3t%GkG=<v$Nw-
z>r0-m5hHOKok?w*cBXS^Bpj;JyaB}G>3MPXh*RbGSsY*eSc_V300s^q(QSx>yg2xr
znw~w7NC(^p$?qQdW)}cJ_$DX-BG2F)$qg$rTIN7N`ol)z1_%LK*9IWxNKE90l^$cQ
z(xC#`Cwp?T=R@9mH2{b{wX7uFS8G+}mgt>*S^$$~@|1(fxd#B0YZe9G!!i3#3xG-|
z_q=-nz@$SifG3T<0VqCN%?AMLohbFXbri^oj1RsPFq7v>fi~X&j*RrV#~Ns4LIST-
z161>->ggR10L+d>)dk18bD*6_m~ixTH2~ZPL{9z4`=AzpdltxqyQZKjIPc(MQqdm<
zb{BA%x`1+W*{q5(Ex&UvvM)&F_pZz8MN}IO0ssdMQU_a%R}SY%q_i4^N}818JbA~t
z10f2o$lg6sr^`2hV;sVGbw`Skb6G!fa!%w91g27WOA2)WFt_Zj6eiDN@;bFs6ha@M
zvLQQ8OF`5efOO%k97Ih4Fr1Wv;EvG%(1xHxo-_dTA*4u`GywcTAUiFLb6KnZGpYj=
ZwQpyC2@&y{><$0`002ovPDHLkV1hXx0~7!N
rename from mobile/android/base/resources/drawable-mdpi/select_all.png
rename to mobile/android/base/resources/drawable-mdpi/ab_select_all.png
index e0dd67c69445979727fc9fdec76c60386524ba92..147044bc6b666349830aaea6b126dc7872dcc3da
GIT binary patch
literal 157
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6i*k&kcwMxr(1I|DDtq{PMJD2
zB4_*c?^c0t%vg?`pOn_67~vwv%&F4Rq0REc=F{h}*krBn*P9yeRZQO5xSuH@;rfA$
zO&8>&Wuz?l8yI;uu;1Y|V3jz)P|d*1_OG0Axg?_r??hS79ZR%#L;&q$@O1TaS?83{
F1OTglGY$X%
index 01d681697f799729aa60bcc03878b8718ef5f705..b8e61f95830c68ba094af6ea5d48e220156fd532
GIT binary patch
literal 128
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzcTX3`kcwMxuP@|fP~dTOY;#iN
zWINu+6D8)5$no&VWM99(OEi_%u`v{sT=_L)Hv_{z#wS7B@3P%sWMHsPU}s=hwx8jF
a=K-dCC7Dgm!jC}aGkCiCxvX<aXaWGDtR|BH
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c371418315ad90566d2441fcecdb3021bd7a6a97
GIT binary patch
literal 1028
zc$@(Q1pE7mP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000BaNkl<Zc-rlo
z--}IA6vs75k|c@bK@v|=LL}kdnfv?qoih)V2U3)#D9zK9G=)5%NG4G-`BfxEGGxM_
z#?LY1-?_fuhdoxiPP^-#qjk^hht-U8_Bm&NKYQ)H*IL^wXti4N+B^Uczyt6AJb)-{
z`|h;U3e{j;w$wb;SE!Gr^R;)WY~{!PY~?q9;@|Ia{XXuWM!St{--hW1kgo(gA?_Z;
z&Qh?;*beO<<tzRBx*9;CI<O>DY+Mc#&XG^$s$cPQCJY3gzk&BG>ox#%_qDzG+AB-&
zufAgaR<7KCfcNe8xE?_8DBAs$&tZDJ#r+N10Z1`xILD<32)oHOAWVS$JlbEAo|Dd1
zKjHd%?EvWZi!k!f#i&nXWDoLQyN2iLW}&3vy{|c~R0F^&epb3X7P6v4sA~b;%PAo|
z>5^IibWx7D>1?jt9PB{6^n^olVZ?Vfs|3K&5$^g7?%KoaQCM%G{#1Cus5$_g``FT^
zOef*`*$9Nosjx?GpWGTX0bmDHV#WTzPDO3-s&VrTE|97KFoYE@dOZ#RnNs7T`3Al>
zq6z>+UzzJ%xp^`U02uWn<{J#CQ~_XzgnJ&22|#lWK%xFnn+IGK0FK54U_byE)3yeT
zi1~RY4ggH0%{K^K6#$02wtGfwoMyM>I-@KO2v(cqg`q3<>E%(1$NLsDb^aS?1Y6Zb
zf{gyeG#HA>{h1z5s0@YWBE`{SS{u>muV9oZ-CrdD#{MjVh_&D`t}X0Pd=K7pS45eU
zOo_DtkTLr<rol2`A%uSwFSb|OEOLwz?`a0G1Md1wR)d(yg;#^Zt3upO_`DtdY6U>?
zyEym53ZN7~VUAH>iFU&_L>5=I)dbnur7VKbRhh1`)3#{Xv|Z_?M`TNl^C*}cXR(8e
z8bqJNh(F=<vEDIbb`(_rFc)hSY|>x+{#|yQ_Xq`mwwUd)UBh!P=vC^@1-RYWBV~#I
z!ov`&ppn6Xc*ibz+s6086CMz-sVJ!ez>wD=e#(y0?86emfcu|d&cGZWc7fA?RU~_h
zQw4x&uH$%%06urR_iF?|@yA@^MV!7VQ2^+!F7YB#`^dy44w3RZ{|x}=rWEgXe_6BF
z4<It}9C_pVi2)$?c9-}`^Pd_L1%M~AF7Z4CHgSI905EoUh@arOKHDY|0D}^Qqc20k
z)Hh6Q*e;0xB!pEgY*^yQd7bx@4nQV9C7%BB{GSC+UYkDv+!l$rsLccL0Ad8-*8mT|
y1MmPm01v<e@Blmj|2IP(fCu0KcmN(i*V-S5DfJ6ivwpt-0000<MNUMnLSTZ9c<u54
rename from mobile/android/base/resources/drawable-xhdpi/copy.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_copy.png
index 364b1692f3eadd2b28e8dbf3d3e83aed90b7ba14..efdc62d52f0c1cc0406df4d1c98efd30efc67cad
GIT binary patch
literal 251
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=hdf;zLn>~)y}g&~kbwx>g>!v&
z-IFI<Y4DZ3E-rul+J(iDrJeiMy(@DbMjN#<$JZ&m^wRWYXMg~K^ABrg8*RQle-}R^
z&|IMd#eWPtBa8NYQEp&kIK&uW>F`U5lYyaO7sIo-KM*YqqKq!zK7}&I{7$@Vb>Q1|
zQHBru8SdW~Wmv(`uuY4>ftBG3{{sykAgxm<vQFTEC<Av0P!~%>21vKU<3<)Bb??z(
d7N`>xW?4UH6TeX#^ZP%D>*?y}vd$@?2>@tMQXK#Q
rename from mobile/android/base/resources/drawable-xhdpi/cut.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_cut.png
index d4e4d81f367d31034dc364793a430f63c7bd19db..b92aed3759a40191c2a9e2bb44fd7882a32376c9
GIT binary patch
literal 890
zc$@)x1BLvFP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0009)Nkl<Zc-rlo
zJ8KkC6o6Bt5DSYGg4kPx6afW61kEOyePrKR3k3^7&`J<Qu#zB%AS57yg#;`_LO_%d
z1Vuy?F&HGGjDKf6AIyczWgZS1XXbi}!z431JNJC&eJ7b1kH`PDC;$bZ02F`%Pyh-b
zS<VKXpJkF0r)m>1q5u?t0{BM&5<bTw_C*wc0#E=7KmnuxXm&@l3$6Z>xqA02*K3X5
z$6#rAv)Mg&z<U6V&T=ppbiT)x%Y|nD1rWRiAj%yUtM76yvit`;L4f=)=fo3kR1`qA
zEVc#@&6?!r$7UUbgh2QfL3!^X09=1`Qq~fhHAyJ+?6rvdKj%E*Q3L?obF$uEz95!a
z#SL-SzX@Qz(c5M%maE^fJm83g#ut+i3jrXpxNhHrC2&)*)R{k3Ucg?8OM1k=fVhp)
zHkiUZAZQP-i6!>j`^9>1xh9`ElvjD%x>>?=ct)W)0M|Fk$`uk7*NEre1VC(WWGPNR
zu(&k1hw`QA15lE<O|jN1aqY{p=z~e$A?|!D<^FBCzCvGs_m#F2B!0z0JE_)d4c5ff
zXPo=4n5=IL*<RotuT(3HYl^k*(y*k)aI^nX6u($+53jn)Q{S<6m1hCMVmd3Pld?Ub
z;>|Eb6GI#8K8JIX%<gk^`uj=mra^`lCOFf=5+0^`;uwWXh}U>I4&&0~1#7YkZ2<g^
zP))o8K%%SFyPw_X$hl8c1devO!&|%nz|<xRZRJja&HgjDi>z81oD$1Ea7$ZUjTi4Y
zANBsBn;=P^l><Ocr`btqgm%gN66?oe2B0vmS0FEx9RM}|w7C15lvZ|&T#yvs2vs6&
z@F9tcSF{L^vH&2?k1_@)SbHyOduMYDLr)VRxI@+&)uS)~rmiQ9!><Vi)6L}(lu8?i
z-FCUKaTu$|SmhD%x=$M-A)7Ejw>wA1;vxW;g${|!X!Bz#m!jFBu<2}xtt4%U`MN1O
zO?#YUQ`F0C@l|U=T(>-6hLDT$%{$*;jO^I0Ga%?QtkAgb`Kz(fys@?`<O#1|jTyn^
zsXAt$qT#~w>>KFoaRs0N6o3NIKa^Ae3P1tqKTIe91)u;FfC5ke3Lr*)0aadE2HvCB
Q)&Kwi07*qoM6N<$g6V;ec>n+a
index bb19810bc2062509e4e4968099a359ad73818728..6160d99f34cf142e33eb07607e14814ace2a0400
GIT binary patch
literal 804
zc$@(w1Ka$GP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0008(Nkl<Zc-rln
zZ%Y(W6viWZAtJJf6cW*w2m;@=rMv33+O82n5lCSeg&`C{A0Y@#Qn4Z`tmq?D{wZDS
zQ*GygJ8*coHN=cFc=o(F%)*@=?(g@UnYnk_W8H4Ir^^Mn02kl_T!0I30WQD=xBwU6
z0$f0rIyYJ^wUT*EG_M}-RRJWShXe#*98c6Q&z>g<z0(2XQ>~}fT63?~XkRzm0h~Na
zJ_G)Vz;~+k>0Ojam_tWk+^hfv|5)G;1bq8qefs-_TJzV~<dtU_w<RDQehZ%k{<)0z
zS-b@p{!s*eS;qV6L1;ukI{XVHZ}Ba_@DK68Blr~=AF#I$VE9IBDFXkJ+un)*hF^@q
zbMmGH;9dR?_*KB`)u0stocx0b{F;mp61)KcoO~R9T_=xYQ3C#E`%sdvHCp!sct2U;
z1^5jaujuoN5Ww(Uxh7BWI|}}lZhIVy5}>x6v!^36@=pG43_g~8p&cN5?J=3qSJ`PT
zB>Qg?kU4o=o8d1_&b(px0tD#f0pFeiJoejR&pofkb4tE_2iK0k4-tH^0+0?~JF?CE
zEff2O2_hxk2{|M`AAx_%@TCX{$6=Y!YfKCi3=;Nmzb5BpfWMsqzR<V8P(;E$p4c?e
zZ158^?_~TWU9&U++zFKo5*U6?zW*}<KdjFySwLI@UP~mQgH>B(;%V@^3jRGOU#@_3
z2^&hncIbrr1Q3J2MadI92`o)Ox`e?XfjeQ5BrrTD|3Ma5BlMj@1!V1n^&nvjoxl<l
z{0$lZLGYUbe@aU#M?m&YSc^zl!sG({O@i+T{6{RUDftow<S*d>izTUR-1Y%}gpxlx
z0$4%-86XKeA$3mv6DNO^1+WBk!m5@)Py5e+*U6g@pwh&#A3s(m5>QA!z@Me$%?Lp8
z?XUuH1%HN;Hz$B4^x>Hx@LxE2%K}(Jg%>&I1#l6(eE|%9$nYrto16=90WQD=xBwU6
i0$hL#Z~-phzv>TQSm5Dw1$~GB0000<MNUMnLSTa0re4(m
rename from mobile/android/base/resources/drawable-xhdpi/paste.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_paste.png
index 6edd4b222ef06eeb46acd9c90ff81bcee1df867f..e82c6651613562a982e14fc344e5a906bc25e7d3
GIT binary patch
literal 427
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@Y=<aSW-r_4f8gufq;9#|!5l
zI(qP+uMCq_r?c>FwXG^!Z|n<}KcKF$bVtVnW($p`?g)(^RxkgXa}*kF6W`&z|1f_a
zH}B8-b^lNEzIBY8RxJxOdO^vg?$b-k*p5EgVZCGS@yw44GuBwf-ZnbOu;PcY_OH#C
z&+lJ-aZYS^6o10%y#WWW-+W<tT0Ok$*sRUjr>`;J@Ty-K5&d@Ye9K-_@$a9ferKo(
z5MTLi&#`syq`4aQz3Y#vbbWk);SPI40OPBirfsM9|Jg23yX@Sv=e7-dpPehep|N-Y
z<C+HHy|;nP`J4XaNeDT7UGe+Ds`Zm|zAR%7W?;~&t6ITcws+@ChE$H__n5!5J&p{v
zu6dtU^WL^$?Z50`2G6KH)%*$1f0hO_?ArdE;Ve7QQw#^P8*=$A87?p}Y}v?qhn*pc
zq2b$h28JyR48N~3frJbAerSVeH~<EYDkB3!L)MSWA~3N4bLlsq-Ux`UtN=v?gQu&X
J%Q~loCIGw_w@&~7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df2021160da6d23a7173015ce5c285e945516ff5
GIT binary patch
literal 1104
zc$@)H1h4yvP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000CRNkl<Zc-rlo
z%WD&H5XXyn2qHy1C{jeEc=4p5C`H6R^0Z0QG(89gsUV1=SQJH3P!PR{iUmE0q9URc
z@t_t|f*uqf@m=D-6Te?*U>uUBn{0Nr@pl+nHtFU!pLtKVU6o4ZzZM6;0dN2u00+PU
zXi<`x@s;u6v59DE^yXk<WTro!`O+Ut&+dw)%lQ2pt`&z;+555GxyfWEzhO(?K$p*A
z10a#kZ>M5&%KllPlmX-=fb9XeC5sXOtk^@vsSK5BRsiA+AnsUH0ARTs+`3dxseyRr
z!%#9i4M2A&`2E>HV&v^Su*wLH^Yn($1Beahj@42G3ckZ@$Ke_4>m3jZt^m9OfIO`Q
z0@oklJ&~{ipz=rcq2URiq0~OF)}!0Q{a@99@EG@68ae<_GOI05OX9Grs_*f7U@8jN
zzohSrN^;d2fKGU8Vd<~(kcjQOR6xA1+1Lf#+(8AQ4B+|D0D!Xhl;x*|@+||Pz!T1?
zMEVh*vD_K}W3`VK5i$P>9<iFQ`3ZnI1Yn;?2!L|N8~`)3JQNciulo&v0<gVksD8-=
z%c@`ofMtsvo-B2=RJ#CBkN|He;CV9uw6=1|6TIF=0Q7=Qsv_Jr1Hi#X9)?X$y8%$>
zX(AcEHv_<_PPVta761T(zx6Np@op0U?Du8q3km>2?UV$7O0?Mo0282Wd;$W%+_PT+
z7&HOE`Y)4FfB+^GfT&dnd>0|`C@27W=;GjHl?01oaZwB~30_gvr^f^UH$HMeVPg~o
z0IthKH&`+&gIs>7uB;G1BeaIFW$2j!K<sVQ^MAVm=n}|L*>o6^?nujUI&2pJj=vm(
ztDlE5{G01`Qvh)Ly=sd)BX$8&e6arLWi<y(nUBMq{-E@0c`zLGqTc`#>9LrMeU8PP
zJ*)ueT(Gmo%Ibhm0C@kc$o4<<G9*+>Q5@((ja~j}u^(vK^3{e*mOk8fS*QRo?!|6U
zt+DgHUI9=+#=P<@y&jKP1JDp6a&ITIH4@f!E;ANV=ixagWwzI%A(#Wuo&aU9Y0JsA
z8RvO!k2uso3T&v@-m;|1zte8t2m;};R9XSh<uNa;*t9VDq1ib?C8=zkFHoOzGc@OI
zvjl1mfWkOtw&t?{9+Z}0GX<-zt12KNG>|gChcpGCa|1nsI|HuH=CO8(3gW$obcfdh
z1bYCw3{pAPc1RRuE`^`l7{4AWL<DaC!UKfR0PszeCpCo7Q2_Xjb5%hv5IPA!H?w^J
z5JDRQ;z<<m5IO<?h0Rp65R3uXL*ORK5P&@d_8f))>>(hD{<H&N4}n9}Lkj?=5cKla
z2!K5VynfcI3Yb99kK9`J0f7oi-C;hz$b`q3r`x-Km~a3b00+PUZ~z<t2fzXFAb$aO
Wh*}oKi<B<_0000<MNUMnLSTaWs_oeT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..614afe56e2508397d1cf650b678e5ebb0e5d6e71
GIT binary patch
literal 233
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=8$4YcLn>~)y=}<VVj$w+$e)_3
zDpnSE|Fug{hJ%5GieO<E|Li11zCAjPTe%hgR55@-L$~Df)ZXIsyZo0o_RW`Gzxg+F
zfOVtngQF+k@gBI$vX67ZH+}~u1{DSermGB-%1+LaTkzwz@A-y&rX{wF6Brmc86ZT%
y=?Sk57&t9h{_-$k3PX4w$}1V-W-@~9{Xd&`eyge9di}>?Ag-sYpUXO@geCy`1xhdg
index 930ca8d95e8bee5a1240fba645d9dab919abd734..9c5156cfd39c9ae0936beb6821ff0aa9c5bfd77e
GIT binary patch
literal 179
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Rh}-6Ar-gY-cl4}5D;(;?4IP}
ze(}vkr{iKQT;_Xt?|f4C>FQX|%zyv~{zl0ct0Va98J`4gX9BUbkrZk2fT%EpNQ1j4
dk|7K-8I1dO>xulk?s^i$^>p=fS?83{1ONx(CE@@8
--- a/mobile/android/base/resources/values-v11/styles.xml
+++ b/mobile/android/base/resources/values-v11/styles.xml
@@ -76,24 +76,28 @@
         <item name="android:textColor">#FF000000</item>
     </style>
 
     <style name="GeckoActionBar" parent="@android:style/Widget.Holo.Light.ActionMode">
         <item name="android:background">@drawable/ab_stacked_transparent_light_holo</item>
     </style>
 
     <style name="GeckoActionBar.Title" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
-        <item name="android:drawableLeft">?android:attr/actionModeCloseDrawable</item>
+        <item name="android:drawableLeft">@drawable/ab_done</item>
         <item name="android:background">@android:color/transparent</item>
         <item name="android:paddingLeft">15dp</item>
         <item name="android:paddingRight">15dp</item>
     </style>
 
     <style name="GeckoActionBar.Button" parent="android:style/Widget.Holo.Light.ActionButton">
-        <item name="android:padding">12dp</item>
+        <item name="android:padding">8dip</item>
+        <!-- The default implementation doesn't do any image scaling. Our custom menus mean we can't just use the same image
+             in both menus and the actionbar without doing some scaling though. -->
+        <item name="android:scaleType">centerInside</item>
     </style>
 
     <style name="GeckoActionBar.Button.MenuButton" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
         <item name="android:scaleType">center</item>
         <item name="android:background">@android:color/transparent</item>
+        <item name="android:src">@drawable/menu_light</item>
     </style>
 
 </resources>
--- a/mobile/android/base/resources/values-v11/themes.xml
+++ b/mobile/android/base/resources/values-v11/themes.xml
@@ -48,15 +48,15 @@
         <item name="topSitesGridItemViewStyle">@style/Widget.TopSitesGridItemView</item>
         <item name="topSitesGridViewStyle">@style/Widget.TopSitesGridView</item>
         <item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>
         <item name="homeListViewStyle">@style/Widget.HomeListView</item>
         <item name="geckoMenuListViewStyle">@style/Widget.GeckoMenuListView</item>
         <item name="menuItemActionModeStyle">@style/GeckoActionBar.Button</item>
         <item name="android:actionModeStyle">@style/GeckoActionBar</item>
         <item name="android:actionButtonStyle">@style/GeckoActionBar.Button</item>
-        <item name="android:actionModeCutDrawable">@drawable/cut</item>
-        <item name="android:actionModeCopyDrawable">@drawable/copy</item>
-        <item name="android:actionModePasteDrawable">@drawable/paste</item>
-        <item name="android:actionModeSelectAllDrawable">@drawable/select_all</item>
+        <item name="android:actionModeCutDrawable">@drawable/ab_cut</item>
+        <item name="android:actionModeCopyDrawable">@drawable/ab_copy</item>
+        <item name="android:actionModePasteDrawable">@drawable/ab_paste</item>
+        <item name="android:actionModeSelectAllDrawable">@drawable/ab_select_all</item>
     </style>
 
 </resources>
--- a/mobile/android/base/widget/ActivityChooserModel.java
+++ b/mobile/android/base/widget/ActivityChooserModel.java
@@ -26,16 +26,21 @@ import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.database.DataSetObservable;
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Xml;
 
 /**
+ * Mozilla: Extra imports.
+ */
+import android.content.pm.ApplicationInfo;
+
+/**
  * Mozilla: Unused import.
  */
 //import com.android.internal.content.PackageMonitor;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -253,16 +258,21 @@ public class ActivityChooserModel extend
      * Monitor for added and removed packages.
      */
     /**
      * Mozilla: Not needed for the application.
      */
     //private final PackageMonitor mPackageMonitor = new DataModelPackageMonitor();
 
     /**
+     * Mozilla: Count to monitor added and removed packages.
+     */
+    private int mApplicationsCount;
+
+    /**
      * Context for accessing resources.
      */
     private final Context mContext;
 
     /**
      * The name of the history file that backs this model.
      */
     private final String mHistoryFileName;
@@ -727,16 +737,25 @@ public class ActivityChooserModel extend
 
     /**
      * Loads the activities for the current intent if needed which is
      * if they are not already loaded for the current intent.
      *
      * @return Whether loading was performed.
      */
     private boolean loadActivitiesIfNeeded() {
+        /**
+         * Mozilla: Hack to find change in the installed/uninstalled applications.
+         */
+        List<ApplicationInfo> applications = mContext.getPackageManager().getInstalledApplications(0);
+        if (applications != null && applications.size() != mApplicationsCount) {
+            mApplicationsCount = applications.size();
+            mReloadActivities = true;
+        }
+
         if (mReloadActivities && mIntent != null) {
             mReloadActivities = false;
             mActivities.clear();
             List<ResolveInfo> resolveInfos = mContext.getPackageManager()
                     .queryIntentActivities(mIntent, 0);
             final int resolveInfoCount = resolveInfos.size();
             for (int i = 0; i < resolveInfoCount; i++) {
                 ResolveInfo resolveInfo = resolveInfos.get(i);
--- a/mobile/android/chrome/content/SelectionHandler.js
+++ b/mobile/android/chrome/content/SelectionHandler.js
@@ -400,63 +400,63 @@ var SelectionHandler = {
   removeAction: function(id) {
     delete this.actions[id];
   },
 
   actions: {
     SELECT_ALL: {
       label: Strings.browser.GetStringFromName("contextmenu.selectAll"),
       id: "selectall_action",
-      icon: "drawable://select_all",
+      icon: "drawable://ab_select_all",
       action: function(aElement) {
         SelectionHandler.selectAll(aElement);
       },
       selector: ClipboardHelper.selectAllContext,
-      order: 1,
+      order: 5,
     },
 
     CUT: {
       label: Strings.browser.GetStringFromName("contextmenu.cut"),
       id: "cut_action",
-      icon: "drawable://cut",
+      icon: "drawable://ab_cut",
       action: function(aElement) {
         let start = aElement.selectionStart;
         let end   = aElement.selectionEnd;
 
         SelectionHandler.copySelection();
         aElement.value = aElement.value.substring(0, start) + aElement.value.substring(end)
 
         // copySelection closes the selection. Show a caret where we just cut the text.
         SelectionHandler.attachCaret(aElement);
       },
-      order: 1,
+      order: 4,
       selector: ClipboardHelper.cutContext,
     },
 
     COPY: {
       label: Strings.browser.GetStringFromName("contextmenu.copy"),
       id: "copy_action",
-      icon: "drawable://copy",
+      icon: "drawable://ab_copy",
       action: function() {
         SelectionHandler.copySelection();
       },
-      order: 1,
+      order: 3,
       selector: ClipboardHelper.getCopyContext(false)
     },
 
     PASTE: {
       label: Strings.browser.GetStringFromName("contextmenu.paste"),
       id: "paste_action",
-      icon: "drawable://paste",
+      icon: "drawable://ab_paste",
       action: function(aElement) {
         ClipboardHelper.paste(aElement);
         SelectionHandler._positionHandles();
         SelectionHandler._updateMenu();
       },
-      order: 1,
+      order: 2,
       selector: ClipboardHelper.pasteContext,
     },
 
     SHARE: {
       label: Strings.browser.GetStringFromName("contextmenu.share"),
       id: "share_action",
       icon: "drawable://ic_menu_share",
       action: function() {
@@ -465,21 +465,22 @@ var SelectionHandler = {
       selector: ClipboardHelper.shareContext,
     },
 
     SEARCH: {
       label: function() {
         return Strings.browser.formatStringFromName("contextmenu.search", [Services.search.defaultEngine.name], 1);
       },
       id: "search_action",
-      icon: "drawable://ic_url_bar_search",
+      icon: "drawable://ab_search",
       action: function() {
         SelectionHandler.searchSelection();
         SelectionHandler._closeSelection();
       },
+      order: 1,
       selector: ClipboardHelper.searchWithContext,
     },
 
   },
 
   /*
    * Called by BrowserEventHandler when the user taps in a form input.
    * Initializes SelectionHandler and positions the caret handle.
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -261,18 +261,19 @@ AboutReader.prototype = {
         this._scrolled = false;
         break;
       case "click":
         if (!this._scrolled)
           this._toggleToolbarVisibility();
         break;
       case "scroll":
         if (!this._scrolled) {
-          this._scrolled = true;
-          this._setToolbarVisibility(false);
+          let isScrollingUp = this._scrollOffset > aEvent.pageY;
+          this._setToolbarVisibility(isScrollingUp);
+          this._scrollOffset = aEvent.pageY;
         }
         break;
       case "popstate":
         if (!aEvent.state)
           this._closeAllDropdowns();
         break;
       case "resize":
         this._updateImageMargins();
@@ -496,32 +497,40 @@ AboutReader.prototype = {
     // Don't allow visible toolbar until banner state is known
     if (this._readingListCount == -1 || this._isReadingListItem == -1)
       return;
 
     if (this._getToolbarVisibility() === visible)
       return;
 
     this._toolbarElement.classList.toggle("toolbar-hidden");
+    this._setSystemUIVisibility(visible);
 
     if (!visible && !this._hasUsedToolbar) {
       this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
       if (!this._hasUsedToolbar) {
         gChromeWin.NativeWindow.toast.show(gStrings.GetStringFromName("aboutReader.toolbarTip"), "short");
 
         Services.prefs.setBoolPref("reader.has_used_toolbar", true);
         this._hasUsedToolbar = true;
       }
     }
   },
 
   _toggleToolbarVisibility: function Reader_toggleToolbarVisibility(visible) {
     this._setToolbarVisibility(!this._getToolbarVisibility());
   },
 
+  _setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
+    gChromeWin.sendMessageToJava({
+      type: "SystemUI:Visibility",
+      visible: visible
+    });
+  },
+
   _loadFromURL: function Reader_loadFromURL(url) {
     this._showProgressDelayed();
 
     gChromeWin.Reader.parseDocumentFromURL(url, function(article) {
       if (article)
         this._showContent(article);
       else
         this._showError(gStrings.GetStringFromName("aboutReader.loadError"));
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -6788,17 +6788,17 @@ var SearchEngines = {
         // POST      everything else                     YES
         return (method == "GET" || method == "") ||
                (form.enctype != "text/plain") && (form.enctype != "multipart/form-data");
       }
     };
     SelectionHandler.addAction({
       id: "search_add_action",
       label: Strings.browser.GetStringFromName("contextmenu.addSearchEngine"),
-      icon: "drawable://ic_url_bar_search",
+      icon: "drawable://ab_add_search_engine",
       selector: filter,
       action: function(aElement) {
         SearchEngines.addEngine(aElement);
       }
     });
   },
 
   uninit: function uninit() {
--- a/mobile/android/themes/core/netError.css
+++ b/mobile/android/themes/core/netError.css
@@ -34,16 +34,20 @@ ul {
   margin: 0;
   list-style: round outside none;
 }
 
 li:not(:last-of-type),
 #errorLongDesc,
 #errorLongContent {
   padding-bottom: 10px;
+}
+
+/* Push the #ignoreWarningButton to the bottom on the blocked site page */
+.blockedsite > #errorPageContainer > #errorLongContent {
   flex: 1;
 }
 
 h1 {
   padding: 1rem 0;
   font-weight: 300;
   border-bottom: 1px solid #e0e2e5;
 }
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -334,23 +334,34 @@ InternalMethods.prototype = {
   },
 
   whenVerified: function(data) {
     if (data.verified) {
       log.debug("already verified");
       return Promise.resolve(data);
     }
     if (!this.whenVerifiedPromise) {
-      this.whenVerifiedPromise = Promise.defer();
       log.debug("whenVerified promise starts polling for verified email");
       this.pollEmailStatus(data.sessionToken, "start");
     }
     return this.whenVerifiedPromise.promise;
   },
 
+  /**
+   * Resend the verification email to the logged-in user.
+   *
+   * @return Promise
+   *         fulfilled: json data returned from xhr call
+   *         rejected: error
+   */
+  resendVerificationEmail: function(data) {
+    this.pollEmailStatus(data.sessionToken, "start");
+    return this.fxAccountsClient.resendVerificationEmail(data.sessionToken);
+  },
+
   notifyObservers: function(topic) {
     log.debug("Notifying observers of " + topic);
     Services.obs.notifyObservers(null, topic, null);
   },
 
   /**
    * Give xpcshell tests an override point for duration testing. This is
    * necessary because the tests need to manipulate the date in order to
@@ -359,22 +370,23 @@ InternalMethods.prototype = {
   now: function() {
     return Date.now();
   },
 
   pollEmailStatus: function pollEmailStatus(sessionToken, why) {
     let myGenerationCount = this.generationCount;
     log.debug("entering pollEmailStatus: " + why + " " + myGenerationCount);
     if (why == "start") {
-      if (this.currentTimer) {
-        // safety check - this case should have been caught on
-        // entry with setSignedInUser
-        throw new Error("Already polling for email status");
+      // If we were already polling, stop and start again.  This could happen
+      // if the user requested the verification email to be resent while we
+      // were already polling for receipt of an earlier email.
+      this.pollTimeRemaining = this.POLL_SESSION;
+      if (!this.whenVerifiedPromise) {
+        this.whenVerifiedPromise = Promise.defer();
       }
-      this.pollTimeRemaining = this.POLL_SESSION;
     }
 
     this.checkEmailStatus(sessionToken)
       .then((response) => {
         log.debug("checkEmailStatus -> " + JSON.stringify(response));
         // Check to see if we're still current.
         // If for some ghastly reason we are not, stop processing.
         if (this.generationCount !== myGenerationCount) {
@@ -482,17 +494,17 @@ this.FxAccounts.prototype = Object.freez
    * @return Promise
    *         The promise resolves to null when the data is saved
    *         successfully and is rejected on error.
    */
   setSignedInUser: function setSignedInUser(credentials) {
     log.debug("setSignedInUser - aborting any existing flows");
     internal.abortExistingFlow();
 
-    let record = {version: this.version, accountData: credentials };
+    let record = {version: this.version, accountData: credentials};
     // Cache a clone of the credentials object.
     internal.signedInUser = JSON.parse(JSON.stringify(record));
 
     // This promise waits for storage, but not for verification.
     // We're telling the caller that this is durable now.
     return internal.signedInUserStorage.set(record)
       .then(() => {
         internal.notifyObservers(ONLOGIN_NOTIFICATION);
@@ -529,16 +541,32 @@ this.FxAccounts.prototype = Object.freez
           // that might not be fulfilled for a long time.
           internal.startVerifiedCheck(data);
         }
         return data;
       });
   },
 
   /**
+   * Resend the verification email fot the currently signed-in user.
+   *
+   */
+  resendVerificationEmail: function resendVerificationEmail() {
+    return this.getSignedInUser().then((data) => {
+      // If the caller is asking for verification to be re-sent, and there is
+      // no signed-in user to begin with, this is probably best regarded as an
+      // error.
+      if (data) {
+        return internal.resendVerificationEmail(data);
+      }
+      throw new Error("Cannot resend verification email; no signed-in user");
+    });
+  },
+
+  /**
    * returns a promise that fires with the assertion.  If there is no verified
    * signed-in user, fires with null.
    */
   getAssertion: function getAssertion(audience) {
     log.debug("enter getAssertion()");
     let mustBeValidUntil = internal.now() + ASSERTION_LIFETIME;
     return internal.getUserAccountData()
       .then((data) => {
--- a/services/fxaccounts/FxAccountsClient.jsm
+++ b/services/fxaccounts/FxAccountsClient.jsm
@@ -96,37 +96,49 @@ this.FxAccountsClient.prototype = {
     return this._request("/raw_password/session/create", "POST", null,
                          {email: hexEmail, password: password});
   },
 
   /**
    * Destroy the current session with the Firefox Account API server
    *
    * @param sessionTokenHex
-   *        The session token endcoded in hex
+   *        The session token encoded in hex
    * @return Promise
    */
   signOut: function (sessionTokenHex) {
     return this._request("/session/destroy", "POST",
       this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
   },
 
   /**
    * Check the verification status of the user's FxA email address
    *
    * @param sessionTokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @return Promise
    */
   recoveryEmailStatus: function (sessionTokenHex) {
     return this._request("/recovery_email/status", "GET",
       this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
   },
 
   /**
+   * Resend the verification email for the user
+   *
+   * @param sessionTokenHex
+   *        The current token encoded in hex
+   * @return Promise
+   */
+  resendVerificationEmail: function(sessionTokenHex) {
+    return this._request("/recovery_email/resend_code", "POST",
+      this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
+  },
+
+  /**
    * Retrieve encryption keys
    *
    * @param keyFetchTokenHex
    *        A one-time use key fetch token encoded in hex
    * @return Promise
    *        Returns a promise that resolves to an object:
    *        {
    *          kA: an encryption key for recevorable data
@@ -165,17 +177,17 @@ this.FxAccountsClient.prototype = {
       };
     });
   },
 
   /**
    * Sends a public key to the FxA API server and returns a signed certificate
    *
    * @param sessionTokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @param serializedPublicKey
    *        A public key (usually generated by jwcrypto)
    * @param lifetime
    *        The lifetime of the certificate
    * @return Promise
    *        Returns a promise that resolves to the signed certificate. The certificate
    *        can be used to generate a Persona assertion.
    */
@@ -218,17 +230,17 @@ this.FxAccountsClient.prototype = {
   },
 
   /**
    * The FxA auth server expects requests to certain endpoints to be authorized using Hawk.
    * Hawk credentials are derived using shared secrets, which depend on the context
    * (e.g. sessionToken vs. keyFetchToken).
    *
    * @param tokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @param context
    *        A context for the credentials
    * @param size
    *        The size in bytes of the expected derived buffer
    * @return credentials
    *        Returns an object:
    *        {
    *          algorithm: sha256
--- a/services/fxaccounts/tests/xpcshell/test_accounts.js
+++ b/services/fxaccounts/tests/xpcshell/test_accounts.js
@@ -59,16 +59,21 @@ function MockFxAccountsClient() {
         kA: expandBytes("11"),
         wrapKB: expandBytes("22")
       };
       deferred.resolve(response);
     });
     return deferred.promise;
   };
 
+  this.resendVerificationEmail = function(sessionToken) {
+    // Return the session token to show that we received it in the first place
+    return Promise.resolve(sessionToken);
+  };
+
   this.signCertificate = function() { throw "no" };
 
   FxAccountsClient.apply(this);
 }
 MockFxAccountsClient.prototype = {
   __proto__: FxAccountsClient.prototype
 }
 
@@ -163,19 +168,17 @@ add_task(function test_get_signed_in_use
   // sign out
   yield account.signOut();
 
   // user should be undefined after sign out
   let result = yield account.getSignedInUser();
   do_check_eq(result, null);
 });
 
-/*
- * Sanity-check that our mocked client is working correctly
- */
+// Sanity-check that our mocked client is working correctly
 add_test(function test_client_mock() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let client = fxa.internal.fxAccountsClient;
   do_check_eq(client._verified, false);
   do_check_eq(typeof client.signIn, "function");
 
@@ -183,22 +186,20 @@ add_test(function test_client_mock() {
   client.recoveryEmailStatus()
     .then(response => {
       do_check_eq(response.verified, false);
       do_test_finished();
       run_next_test();
     });
 });
 
-/*
- * Sign in a user, and after a little while, verify the user's email.
- * Right after signing in the user, we should get the 'onlogin' notification.
- * Polling should detect that the email is verified, and eventually
- * 'onverified' should be observed
- */
+// Sign in a user, and after a little while, verify the user's email.
+// Right after signing in the user, we should get the 'onlogin' notification.
+// Polling should detect that the email is verified, and eventually
+// 'onverified' should be observed
 add_test(function test_verification_poll() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let test_user = getTestUser("francine");
   let login_notification_received = false;
 
   makeObserver(ONVERIFIED_NOTIFICATION, function() {
@@ -219,29 +220,27 @@ add_test(function test_verification_poll
     login_notification_received = true;
   });
 
   fxa.setSignedInUser(test_user).then(() => {
     fxa.internal.getUserAccountData().then(user => {
       // The user is signing in, but email has not been verified yet
       do_check_eq(user.verified, false);
       do_timeout(200, function() {
-        // Mock email verification ...
+        log.debug("Mocking verification of francine's email");
         fxa.internal.fxAccountsClient._email = test_user.email;
         fxa.internal.fxAccountsClient._verified = true;
       });
     });
   });
 });
 
-/*
- * Sign in the user, but never verify the email.  The check-email
- * poll should time out.  No verifiedlogin event should be observed, and the
- * internal whenVerified promise should be rejected
- */
+// Sign in the user, but never verify the email.  The check-email
+// poll should time out.  No verifiedlogin event should be observed, and the
+// internal whenVerified promise should be rejected
 add_test(function test_polling_timeout() {
   do_test_pending();
 
   // This test could be better - the onverified observer might fire on
   // somebody else's stack, and we're not making sure that we're not receiving
   // such a message. In other words, this tests either failure, or success, but
   // not both.
 
@@ -298,19 +297,17 @@ add_test(function test_getKeys() {
           do_test_finished();
           run_next_test();
         });
       });
     });
   });
 });
 
-/*
- * getKeys with no keyFetchToken should trigger signOut
- */
+// getKeys with no keyFetchToken should trigger signOut
 add_test(function test_getKeys_no_token() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let user = getTestUser("lettuce.protheroe");
   delete user.keyFetchToken
 
   makeObserver(ONLOGOUT_NOTIFICATION, function() {
@@ -321,21 +318,19 @@ add_test(function test_getKeys_no_token(
     });
   });
 
   fxa.setSignedInUser(user).then((user) => {
     fxa.internal.getKeys();
   });
 });
 
-/*
- * Alice (User A) signs up but never verifies her email.  Then Bob (User B)
- * signs in with a verified email.  Ensure that no sign-in events are triggered
- * on Alice's behalf.  In the end, Bob should be the signed-in user.
- */
+// Alice (User A) signs up but never verifies her email.  Then Bob (User B)
+// signs in with a verified email.  Ensure that no sign-in events are triggered
+// on Alice's behalf.  In the end, Bob should be the signed-in user.
 add_test(function test_overlapping_signins() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
   let bob = getTestUser("bob");
 
   makeObserver(ONVERIFIED_NOTIFICATION, function() {
@@ -452,16 +447,74 @@ add_task(function test_getAssertion() {
   do_check_eq(fxa.internal.cert.validUntil, now + 24*3600*1000 + (6*3600*1000));
   exp = Number(payload.exp);
   do_check_true(start + 2*60*1000 <= exp);
   do_check_true(exp <= finish + 2*60*1000);
 
   _("----- DONE ----\n");
 });
 
+add_task(function test_resend_email_not_signed_in() {
+  let fxa = new MockFxAccounts();
+
+  try {
+    yield fxa.resendVerificationEmail();
+  } catch(err) {
+    do_check_eq(err.message,
+      "Cannot resend verification email; no signed-in user");
+    do_test_finished();
+    run_next_test();
+    return;
+  }
+  do_throw("Should not be able to resend email when nobody is signed in");
+});
+
+add_task(function test_resend_email() {
+  do_test_pending();
+
+  let fxa = new MockFxAccounts();
+  let alice = getTestUser("alice");
+
+  do_check_eq(fxa.internal.generationCount, 0);
+
+  // Alice is the user signing in; her email is unverified.
+  fxa.setSignedInUser(alice).then(() => {
+    log.debug("Alice signing in");
+
+    // We're polling for the first email
+    do_check_eq(fxa.internal.generationCount, 1);
+
+    // The polling timer is ticking
+    do_check_true(fxa.internal.currentTimer > 0);
+
+    fxa.internal.getUserAccountData().then(user => {
+      do_check_eq(user.email, alice.email);
+      do_check_eq(user.verified, false);
+      log.debug("Alice wants verification email resent");
+
+      fxa.resendVerificationEmail().then((result) => {
+        // Mock server response; ensures that the session token actually was
+        // passed to the client to make the hawk call
+        do_check_eq(result, "alice's session token");
+
+        // Timer was not restarted
+        do_check_eq(fxa.internal.generationCount, 1);
+
+        // Timer is still ticking
+        do_check_true(fxa.internal.currentTimer > 0);
+
+        // Ok abort polling before we go on to the next test
+        fxa.internal.abortExistingFlow();
+        do_test_finished();
+        run_next_test();
+      });
+    });
+  });
+});
+
 /*
  * End of tests.
  * Utility functions follow.
  */
 
 function expandHex(two_hex) {
   // Return a 64-character hex string, encoding 32 identical bytes.
   let eight_hex = two_hex + two_hex + two_hex + two_hex;
--- a/toolkit/themes/windows/global/menulist-aero.css
+++ b/toolkit/themes/windows/global/menulist-aero.css
@@ -16,16 +16,20 @@ menulist:-moz-focusring:not([open="true"
   }
 
   .menulist-label {
     margin-top: -1px !important;
     margin-bottom: -1px !important;
     -moz-margin-start: 0 !important;
   }
 
+  .menulist-description {
+    -moz-margin-start: 1ex !important;
+  }
+
   menulist:not([editable="true"]) > .menulist-dropmarker {
     margin-top: -2px;
     -moz-margin-start: 3px;
     -moz-margin-end: -3px;
   }
 
   .menulist-icon {
     margin-top: -1px;