Merge m-c to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 16 Oct 2014 16:10:53 +0200
changeset 210757 ef38d26cac45c3c80b3e823eebcfcef2afbb2c93
parent 210756 451ef271a2479d3f3ac3c3ce67503e6ca1fdf7c3 (current diff)
parent 210706 77f3ca1fe052ca3eced92af99221e29a7fc6c36b (diff)
child 210758 ebf4483757474f625926717d4d0e05208b5bb078
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone36.0a1
Merge m-c to mozilla-inbound
configure.in
--- a/b2g/chrome/content/devtools/adb.js
+++ b/b2g/chrome/content/devtools/adb.js
@@ -3,50 +3,46 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // This file is only loaded on Gonk to manage ADB state
 
+const { utils: Cu } = Components;
+
+const DEBUG = false;
+var debug = function(str) {
+  dump("AdbController: " + str + "\n");
+}
+
 let AdbController = {
-  DEBUG: false,
   locked: undefined,
   remoteDebuggerEnabled: undefined,
   lockEnabled: undefined,
   disableAdbTimer: null,
   disableAdbTimeoutHours: 12,
   umsActive: false,
 
-  debug: function(str) {
-    dump("AdbController: " + str + "\n");
-  },
-
   setLockscreenEnabled: function(value) {
     this.lockEnabled = value;
-    if (this.DEBUG) {
-      this.debug("setLockscreenEnabled = " + this.lockEnabled);
-    }
+    DEBUG && debug("setLockscreenEnabled = " + this.lockEnabled);
     this.updateState();
   },
 
   setLockscreenState: function(value) {
     this.locked = value;
-    if (this.DEBUG) {
-      this.debug("setLockscreenState = " + this.locked);
-    }
+    DEBUG && debug("setLockscreenState = " + this.locked);
     this.updateState();
   },
 
   setRemoteDebuggerState: function(value) {
     this.remoteDebuggerEnabled = value;
-    if (this.DEBUG) {
-      this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
-    }
+    DEBUG && debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
     this.updateState();
   },
 
   startDisableAdbTimer: function() {
     if (this.disableAdbTimer) {
       this.disableAdbTimer.cancel();
     } else {
       this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
@@ -54,48 +50,42 @@ let AdbController = {
         this.disableAdbTimeoutHours =
           Services.prefs.getIntPref("b2g.adb.timeout-hours");
       } catch (e) {
         // This happens if the pref doesn't exist, in which case
         // disableAdbTimeoutHours will still be set to the default.
       }
     }
     if (this.disableAdbTimeoutHours <= 0) {
-      if (this.DEBUG) {
-        this.debug("Timer to disable ADB not started due to zero timeout");
-      }
+      DEBUG && debug("Timer to disable ADB not started due to zero timeout");
       return;
     }
 
-    if (this.DEBUG) {
-      this.debug("Starting timer to disable ADB in " +
-                 this.disableAdbTimeoutHours + " hours");
-    }
+    DEBUG && debug("Starting timer to disable ADB in " +
+                   this.disableAdbTimeoutHours + " hours");
     let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000;
     this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds,
                                           Ci.nsITimer.TYPE_ONE_SHOT);
   },
 
   stopDisableAdbTimer: function() {
-    if (this.DEBUG) {
-      this.debug("Stopping timer to disable ADB");
-    }
+    DEBUG && debug("Stopping timer to disable ADB");
     if (this.disableAdbTimer) {
       this.disableAdbTimer.cancel();
       this.disableAdbTimer = null;
     }
   },
 
   notify: function(aTimer) {
     if (aTimer == this.disableAdbTimer) {
       this.disableAdbTimer = null;
       // The following dump will be the last thing that shows up in logcat,
       // and will at least give the user a clue about why logcat was
       // disconnected, if the user happens to be using logcat.
-      dump("AdbController: ADB timer expired - disabling ADB\n");
+      debug("ADB timer expired - disabling ADB\n");
       navigator.mozSettings.createLock().set(
         {'debugger.remote-mode': 'disabled'});
     }
   },
 
   updateState: function() {
     this.umsActive = false;
     this.storages = navigator.getDeviceStorages('sdcard');
@@ -105,47 +95,40 @@ let AdbController = {
   updateStorageState: function(storageIndex) {
     if (storageIndex >= this.storages.length) {
       // We've iterated through all of the storage objects, now we can
       // really do updateStateInternal.
       this.updateStateInternal();
       return;
     }
     let storage = this.storages[storageIndex];
-    if (this.DEBUG) {
-      this.debug("Checking availability of storage: '" +
-                 storage.storageName);
-    }
+    DEBUG && debug("Checking availability of storage: '" + storage.storageName);
 
     let req = storage.available();
     req.onsuccess = function(e) {
-      if (this.DEBUG) {
-        this.debug("Storage: '" + storage.storageName + "' is '" +
-                   e.target.result);
-      }
+      DEBUG && debug("Storage: '" + storage.storageName + "' is '" + e.target.result);
       if (e.target.result == 'shared') {
         // We've found a storage area that's being shared with the PC.
         // We can stop looking now.
         this.umsActive = true;
         this.updateStateInternal();
         return;
       }
       this.updateStorageState(storageIndex + 1);
     }.bind(this);
     req.onerror = function(e) {
-      dump("AdbController: error querying storage availability for '" +
-           this.storages[storageIndex].storageName + "' (ignoring)\n");
+
+      Cu.reportError("AdbController: error querying storage availability for '" +
+                     this.storages[storageIndex].storageName + "' (ignoring)\n");
       this.updateStorageState(storageIndex + 1);
     }.bind(this);
   },
 
   updateStateInternal: function() {
-    if (this.DEBUG) {
-      this.debug("updateStateInternal: called");
-    }
+    DEBUG && debug("updateStateInternal: called");
 
     if (this.remoteDebuggerEnabled === undefined ||
         this.lockEnabled === undefined ||
         this.locked === undefined) {
       // Part of initializing the settings database will cause the observers
       // to trigger. We want to wait until both have been initialized before
       // we start changing ther adb state. Without this then we can wind up
       // toggling adb off and back on again (or on and back off again).
@@ -157,28 +140,24 @@ let AdbController = {
       // receive the unlock event we haven't yet received the rde event, so
       // we turn adb off momentarily, which disconnects a logcat that might
       // be running. Changing the defaults (in AdbController) just moves the
       // problem to a different phone, which has adb disabled by default and
       // we wind up turning on adb for a short period when we shouldn't.
       //
       // By waiting until both values are properly initialized, we avoid
       // turning adb on or off accidentally.
-      if (this.DEBUG) {
-        this.debug("updateState: Waiting for all vars to be initialized");
-      }
+      DEBUG && debug("updateState: Waiting for all vars to be initialized");
       return;
     }
 
     // Check if we have a remote debugging session going on. If so, we won't
     // disable adb even if the screen is locked.
     let isDebugging = USBRemoteDebugger.isDebugging;
-    if (this.DEBUG) {
-      this.debug("isDebugging=" + isDebugging);
-    }
+    DEBUG && debug("isDebugging=" + isDebugging);
 
     // If USB Mass Storage, USB tethering, or a debug session is active,
     // then we don't want to disable adb in an automatic fashion (i.e.
     // when the screen locks or due to timeout).
     let sysUsbConfig = libcutils.property_get("sys.usb.config");
     let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0);
     let usbFuncActive = rndisActive || this.umsActive || isDebugging;
 
@@ -194,23 +173,21 @@ let AdbController = {
         // we want adb enabled all of the time.
         enableAdb = true;
         useDisableAdbTimer = false;
       }
     } catch (e) {
       // This means that the pref doesn't exist. Which is fine. We just leave
       // enableAdb alone.
     }
-    if (this.DEBUG) {
-      this.debug("updateState: enableAdb = " + enableAdb +
-                 " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
-                 " lockEnabled = " + this.lockEnabled +
-                 " locked = " + this.locked +
-                 " usbFuncActive = " + usbFuncActive);
-    }
+    DEBUG && debug("updateState: enableAdb = " + enableAdb +
+                   " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
+                   " lockEnabled = " + this.lockEnabled +
+                   " locked = " + this.locked +
+                   " usbFuncActive = " + usbFuncActive);
 
     // Configure adb.
     let currentConfig = libcutils.property_get("persist.sys.usb.config");
     let configFuncs = currentConfig.split(",");
     let adbIndex = configFuncs.indexOf("adb");
 
     if (enableAdb) {
       // Add adb to the list of functions, if not already present
@@ -220,32 +197,31 @@ let AdbController = {
     } else {
       // Remove adb from the list of functions, if present
       if (adbIndex >= 0) {
         configFuncs.splice(adbIndex, 1);
       }
     }
     let newConfig = configFuncs.join(",");
     if (newConfig != currentConfig) {
-      if (this.DEBUG) {
-        this.debug("updateState: currentConfig = " + currentConfig);
-        this.debug("updateState:     newConfig = " + newConfig);
-      }
+      DEBUG && debug("updateState: currentConfig = " + currentConfig);
+      DEBUG && debug("updateState:     newConfig = " + newConfig);
       try {
         libcutils.property_set("persist.sys.usb.config", newConfig);
       } catch(e) {
-        dump("Error configuring adb: " + e);
+        Cu.reportError("Error configuring adb: " + e);
       }
     }
     if (useDisableAdbTimer) {
       if (enableAdb && !usbFuncActive) {
         this.startDisableAdbTimer();
       } else {
         this.stopDisableAdbTimer();
       }
     }
   }
+
 };
 
 SettingsListener.observe("lockscreen.locked", false,
                          AdbController.setLockscreenState.bind(AdbController));
 SettingsListener.observe("lockscreen.enabled", false,
                          AdbController.setLockscreenEnabled.bind(AdbController));
--- 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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- 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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
--- 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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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": "210585c281313afd89e28d6df035201e56dc80e8", 
+    "revision": "8017299c3eb7b82bdaee1334994f546c11eb16ab", 
     "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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="841d0d7d1b879f0ff4b5a8727f5dd23c7b0000a9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <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="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <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/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1375,16 +1375,23 @@ pref("devtools.debugger.ui.panes-visible
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
 
 // Enable the Profiler and the Timeline
 pref("devtools.profiler.enabled", true);
 pref("devtools.timeline.enabled", false);
 
+// Enable perftools via build command
+#ifdef MOZ_DEVTOOLS_PERFTOOLS
+  pref("devtools.performance_dev.enabled", true);
+#else
+  pref("devtools.performance_dev.enabled", false);
+#endif
+
 // The default Profiler UI settings
 pref("devtools.profiler.ui.show-platform-data", false);
 
 // The default cache UI setting
 pref("devtools.cache.disabled", false);
 
 // Enable the Network Monitor
 pref("devtools.netmonitor.enabled", true);
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -123,17 +123,17 @@
             <description class="text-blurb" id="communityExperimentalDesc">
               &community.exp.start;<label class="text-link" href="http://www.mozilla.org/">&community.exp.mozillaLink;</label>&community.exp.middle;<label class="text-link" href="about:credits">&community.exp.creditsLink;</label>&community.exp.end;
             </description>
           </vbox>
           <description class="text-blurb" id="communityDesc">
             &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end3;
           </description>
           <description class="text-blurb" id="contributeDesc">
-            &contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
+              &helpus.start;<label class="text-link" href="https://sendto.mozilla.org/page/contribute/Give-Now?source=mozillaorg_default_footer&#38;ref=firefox_about&#38;utm_campaign=firefox_about&#38;tm_source=firefox&#38;tm_medium=referral&#38;utm_content=20140929_FireFoxAbout">&helpus.donateLink;</label>&helpus.middle;<label class="text-link" href="http://www.mozilla.org/contribute/">&helpus.getInvolvedLink;</label>&helpus.end;
           </description>
         </vbox>
       </vbox>
     </hbox>
     <vbox id="bottomBox">
       <hbox pack="center">
         <label class="text-link bottom-link" href="about:license">&bottomLinks.license;</label>
         <label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
--- a/browser/base/content/newtab/updater.js
+++ b/browser/base/content/newtab/updater.js
@@ -149,32 +149,29 @@ let gUpdater = {
 
   /**
    * Tries to fill empty cells with new links if available.
    * @param aLinks The array of links.
    * @param aCallback The callback to call when finished.
    */
   _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
     let {cells, sites} = gGrid;
-    let batch = [];
 
     // Find empty cells and fill them.
-    sites.forEach(function (aSite, aIndex) {
+    Promise.all(sites.map((aSite, aIndex) => {
       if (aSite || !aLinks[aIndex])
-        return;
+        return null;
 
-      batch.push(new Promise(resolve => {
+      return new Promise(resolve => {
         // Create the new site and fade it in.
         let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
 
         // Set the site's initial opacity to zero.
         site.node.style.opacity = 0;
 
         // Flush all style changes for the dynamically inserted site to make
         // the fade-in transition work.
         window.getComputedStyle(site.node).opacity;
         gTransformation.showSite(site, resolve);
-      }));
-    });
-
-    Promise.all(batch).then(aCallback);
+      });
+    })).then(aCallback).catch(console.exception);
   }
 };
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -44,16 +44,17 @@ skip-if = e10s # Bug 915547 (social prov
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_errorPage.js]
 [browser_social_flyout.js]
 skip-if = e10s # when we backed out bug 1047603, this test broke.
 [browser_social_isVisible.js]
 [browser_social_marks.js]
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_multiprovider.js]
+skip-if = e10s # Bug 1069162 - lots of orange
 [browser_social_multiworker.js]
 [browser_social_perwindowPB.js]
 [browser_social_sidebar.js]
 [browser_social_status.js]
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_window.js]
 [browser_social_workercrash.js]
 skip-if = !crashreporter
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -918,17 +918,17 @@ const CustomizableWidgets = [
     tooltiptext: "email-link-button.tooltiptext3",
     onCommand: function(aEvent) {
       let win = aEvent.view;
       win.MailIntegration.sendLinkForWindow(win.content);
     }
   }, {
     id: "loop-call-button",
     type: "custom",
-    label: "loop-call-button2.label",
+    label: "loop-call-button3.label",
     tooltiptext: "loop-call-button2.tooltiptext",
     defaultArea: CustomizableUI.AREA_NAVBAR,
     introducedInVersion: 1,
     onBuild: function(aDocument) {
       let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
       node.setAttribute("id", this.id);
       node.classList.add("toolbarbutton-1");
       node.classList.add("chromeclass-toolbar-additional");
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -81,16 +81,20 @@ browser.jar:
     content/browser/devtools/webaudioeditor/controller.js              (webaudioeditor/controller.js)
     content/browser/devtools/webaudioeditor/views/utils.js             (webaudioeditor/views/utils.js)
     content/browser/devtools/webaudioeditor/views/context.js           (webaudioeditor/views/context.js)
     content/browser/devtools/webaudioeditor/views/inspector.js         (webaudioeditor/views/inspector.js)
     content/browser/devtools/profiler.xul                              (profiler/profiler.xul)
     content/browser/devtools/profiler.js                               (profiler/profiler.js)
     content/browser/devtools/ui-recordings.js                          (profiler/ui-recordings.js)
     content/browser/devtools/ui-profile.js                             (profiler/ui-profile.js)
+#ifdef MOZ_DEVTOOLS_PERFTOOLS
+    content/browser/devtools/performance.xul                           (performance/performance.xul)
+    content/browser/devtools/performance.js                            (performance/performance.js)
+#endif
     content/browser/devtools/responsivedesign/resize-commands.js       (responsivedesign/resize-commands.js)
     content/browser/devtools/commandline.css                           (commandline/commandline.css)
     content/browser/devtools/commandlineoutput.xhtml                   (commandline/commandlineoutput.xhtml)
     content/browser/devtools/commandlinetooltip.xhtml                  (commandline/commandlinetooltip.xhtml)
     content/browser/devtools/commandline/commands-index.js             (commandline/commands-index.js)
     content/browser/devtools/framework/toolbox-window.xul              (framework/toolbox-window.xul)
     content/browser/devtools/framework/toolbox-options.xul             (framework/toolbox-options.xul)
     content/browser/devtools/framework/toolbox-options.js              (framework/toolbox-options.js)
--- a/browser/devtools/main.js
+++ b/browser/devtools/main.js
@@ -26,16 +26,17 @@ loader.lazyGetter(this, "OptionsPanel", 
 loader.lazyGetter(this, "InspectorPanel", () => require("devtools/inspector/inspector-panel").InspectorPanel);
 loader.lazyGetter(this, "WebConsolePanel", () => require("devtools/webconsole/panel").WebConsolePanel);
 loader.lazyGetter(this, "DebuggerPanel", () => require("devtools/debugger/panel").DebuggerPanel);
 loader.lazyGetter(this, "StyleEditorPanel", () => require("devtools/styleeditor/styleeditor-panel").StyleEditorPanel);
 loader.lazyGetter(this, "ShaderEditorPanel", () => require("devtools/shadereditor/panel").ShaderEditorPanel);
 loader.lazyGetter(this, "CanvasDebuggerPanel", () => require("devtools/canvasdebugger/panel").CanvasDebuggerPanel);
 loader.lazyGetter(this, "WebAudioEditorPanel", () => require("devtools/webaudioeditor/panel").WebAudioEditorPanel);
 loader.lazyGetter(this, "ProfilerPanel", () => require("devtools/profiler/panel").ProfilerPanel);
+loader.lazyGetter(this, "PerformancePanel", () => require("devtools/performance/panel").PerformancePanel);
 loader.lazyGetter(this, "TimelinePanel", () => require("devtools/timeline/panel").TimelinePanel);
 loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/netmonitor/panel").NetMonitorPanel);
 loader.lazyGetter(this, "StoragePanel", () => require("devtools/storage/panel").StoragePanel);
 loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/scratchpad/scratchpad-panel").ScratchpadPanel);
 
 // Strings
 const toolboxProps = "chrome://browser/locale/devtools/toolbox.properties";
 const inspectorProps = "chrome://browser/locale/devtools/inspector.properties";
@@ -269,16 +270,42 @@ Tools.jsprofiler = {
     return !target.isAddon && (!target.isApp || target.form.profilerActor);
   },
 
   build: function (frame, target) {
     return new ProfilerPanel(frame, target);
   }
 };
 
+Tools.performance = {
+  id: "performance",
+  ordinal: 19,
+  icon: "chrome://browser/skin/devtools/tool-profiler.svg",
+  invertIconForLightTheme: true,
+  url: "chrome://browser/content/devtools/performance.xul",
+  // TODO bug 1082695 audit the Performance tools labels
+  label: "Performance++", //l10n("profiler.label2", profilerStrings),
+  panelLabel: "Performance++", //l10n("profiler.panelLabel2", profilerStrings),
+  tooltip: l10n("profiler.tooltip2", profilerStrings),
+  accesskey: l10n("profiler.accesskey", profilerStrings),
+  key: l10n("profiler.commandkey2", profilerStrings),
+  modifiers: "shift",
+  inMenu: true,
+
+  isTargetSupported: function (target) {
+    // Hide the profiler when debugging devices pre bug 1046394,
+    // that don't expose profiler actor in content processes.
+    return !target.isAddon && (!target.isApp || target.form.profilerActor);
+  },
+
+  build: function (frame, target) {
+    return new PerformancePanel(frame, target);
+  }
+};
+
 Tools.timeline = {
   id: "timeline",
   ordinal: 8,
   visibilityswitch: "devtools.timeline.enabled",
   icon: "chrome://browser/skin/devtools/tool-network.svg",
   invertIconForLightTheme: true,
   url: "chrome://browser/content/devtools/timeline/timeline.xul",
   label: l10n("timeline.label", timelineStrings),
@@ -399,16 +426,26 @@ let defaultTools = [
   Tools.webAudioEditor,
   Tools.jsprofiler,
   Tools.timeline,
   Tools.netMonitor,
   Tools.storage,
   Tools.scratchpad
 ];
 
+// Only enable in-development performance tools if `--enable-devtools-perf`
+// used in build, turning on `devtools.performance_dev.enabled`.
+// Add to normal `defaultTools` when ready for normal release,
+// pull out MOZ_DEVTOOLS_PERFTOOLS setting in `./configure.in`, and
+// leave config on in `./browser/app/profile/firefox.js`, and always
+// build in `./browser/devtools/moz.build`.
+if (Services.prefs.getBoolPref("devtools.performance_dev.enabled")) {
+  defaultTools.push(Tools.performance);
+}
+
 exports.defaultTools = defaultTools;
 
 for (let definition of defaultTools) {
   gDevTools.registerTool(definition);
 }
 
 Tools.darkTheme = {
   id: "dark",
--- a/browser/devtools/moz.build
+++ b/browser/devtools/moz.build
@@ -28,16 +28,19 @@ DIRS += [
     'styleinspector',
     'tilt',
     'timeline',
     'webaudioeditor',
     'webconsole',
     'webide',
 ]
 
+if CONFIG['MOZ_DEVTOOLS_PERFTOOLS']:
+  DIRS += ['performance']
+
 EXTRA_COMPONENTS += [
     'devtools-clhandler.js',
     'devtools-clhandler.manifest',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 EXTRA_JS_MODULES.devtools += [
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/moz.build
@@ -0,0 +1,8 @@
+# vim: set filetype=python:
+# 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/.
+
+EXTRA_JS_MODULES.devtools.performance += [
+    'panel.js'
+]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/panel.js
@@ -0,0 +1,62 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const {Cc, Ci, Cu, Cr} = require("chrome");
+
+Cu.import("resource://gre/modules/Task.jsm");
+
+loader.lazyRequireGetter(this, "promise");
+loader.lazyRequireGetter(this, "EventEmitter",
+  "devtools/toolkit/event-emitter");
+
+function PerformancePanel(iframeWindow, toolbox) {
+  this.panelWin = iframeWindow;
+  this._toolbox = toolbox;
+
+  EventEmitter.decorate(this);
+}
+
+exports.PerformancePanel = PerformancePanel;
+
+PerformancePanel.prototype = {
+  /**
+   * Open is effectively an asynchronous constructor.
+   *
+   * @return object
+   *         A promise that is resolved when the Profiler completes opening.
+   */
+  open: Task.async(function*() {
+    this.panelWin.gToolbox = this._toolbox;
+    this.panelWin.gTarget = this.target;
+
+    // Mock Front for now
+    let gFront = {};
+    EventEmitter.decorate(gFront);
+    this.panelWin.gFront = gFront;
+
+    yield this.panelWin.startupPerformance();
+
+    this.isReady = true;
+    this.emit("ready");
+    return this;
+  }),
+
+  // DevToolPanel API
+
+  get target() this._toolbox.target,
+
+  destroy: Task.async(function*() {
+    // Make sure this panel is not already destroyed.
+    if (this._destroyed) {
+      return;
+    }
+
+    yield this.panelWin.shutdownPerformance();
+    this.emit("destroyed");
+    this._destroyed = true;
+  })
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/performance.js
@@ -0,0 +1,97 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/devtools/Loader.jsm");
+Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
+
+devtools.lazyRequireGetter(this, "Services");
+devtools.lazyRequireGetter(this, "promise");
+devtools.lazyRequireGetter(this, "EventEmitter",
+  "devtools/toolkit/event-emitter");
+devtools.lazyRequireGetter(this, "DevToolsUtils",
+  "devtools/toolkit/DevToolsUtils");
+
+/**
+ * The current target and the profiler connection, set by this tool's host.
+ */
+let gToolbox, gTarget, gFront;
+
+/**
+ * Initializes the profiler controller and views.
+ */
+let startupPerformance = Task.async(function*() {
+  yield promise.all([
+    PrefObserver.register(),
+    EventsHandler.initialize()
+  ]);
+});
+
+/**
+ * Destroys the profiler controller and views.
+ */
+let shutdownPerformance = Task.async(function*() {
+  yield promise.all([
+    PrefObserver.unregister(),
+    EventsHandler.destroy()
+  ]);
+});
+
+/**
+ * Observes pref changes on the devtools.profiler branch and triggers the
+ * required frontend modifications.
+ */
+let PrefObserver = {
+  register: function() {
+    this.branch = Services.prefs.getBranch("devtools.profiler.");
+    this.branch.addObserver("", this, false);
+  },
+  unregister: function() {
+    this.branch.removeObserver("", this);
+  },
+  observe: function(subject, topic, pref) {
+    Prefs.refresh();
+  }
+};
+
+/**
+ * Functions handling target-related lifetime events.
+ */
+let EventsHandler = {
+  /**
+   * Listen for events emitted by the current tab target.
+   */
+  initialize: function() {
+  },
+
+  /**
+   * Remove events emitted by the current tab target.
+   */
+  destroy: function() {
+  }
+};
+
+/**
+ * Shortcuts for accessing various profiler preferences.
+ */
+const Prefs = new ViewHelpers.Prefs("devtools.profiler", {
+});
+
+/**
+ * Convenient way of emitting events from the panel window.
+ */
+EventEmitter.decorate(this);
+
+/**
+ * DOM query helpers.
+ */
+function $(selector, target = document) {
+  return target.querySelector(selector);
+}
+function $$(selector, target = document) {
+  return target.querySelectorAll(selector);
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/performance.xul
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/performance.css" type="text/css"?>
+<!DOCTYPE window [
+  <!ENTITY % profilerDTD SYSTEM "chrome://browser/locale/devtools/profiler.dtd">
+  %profilerDTD;
+]>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script src="chrome://browser/content/devtools/theme-switching.js"/>
+  <script type="application/javascript" src="performance.js"/>
+
+  <vbox class="theme-body" flex="1">
+    <toolbar id="performance-toolbar" class="devtools-toolbar">
+      <hbox id="performance-toolbar-controls-recordings" class="devtools-toolbarbutton-group">
+        <toolbarbutton id="record-button"
+                       class="devtools-toolbarbutton"
+                       tooltiptext="&profilerUI.recordButton.tooltip;"/>
+        <toolbarbutton id="clear-button"
+                       class="devtools-toolbarbutton"
+                       label="&profilerUI.clearButton;"/>
+      </hbox>
+      <spacer flex="1"></spacer>
+      <hbox id="performance-toolbar-controls-storage" class="devtools-toolbarbutton-group">
+        <toolbarbutton id="import-button"
+                       class="devtools-toolbarbutton"
+                       label="&profilerUI.importButton;"/>
+      </hbox>
+    </toolbar>
+    <splitter class="devtools-horizontal-splitter" />
+    <box id="overview-pane"
+         class="devtools-responsive-container"
+         flex="1">
+    </box>
+    <splitter class="devtools-horizontal-splitter" />
+    <box id="details-pane"
+         class="devtools-responsive-container"
+         flex="1">
+    </box>
+  </vbox>
+</window>
--- a/browser/devtools/webaudioeditor/test/browser.ini
+++ b/browser/devtools/webaudioeditor/test/browser.ini
@@ -17,16 +17,17 @@ support-files =
 
 [browser_audionode-actor-get-param-flags.js]
 [browser_audionode-actor-get-params-01.js]
 [browser_audionode-actor-get-params-02.js]
 [browser_audionode-actor-get-set-param.js]
 [browser_audionode-actor-get-type.js]
 [browser_audionode-actor-is-source.js]
 [browser_audionode-actor-bypass.js]
+[browser_audionode-actor-connectnode-disconnect.js]
 [browser_webaudio-actor-simple.js]
 [browser_webaudio-actor-destroy-node.js]
 [browser_webaudio-actor-connect-param.js]
 
 [browser_wa_destroy-node-01.js]
 
 [browser_wa_first-run.js]
 [browser_wa_reset-01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webaudioeditor/test/browser_audionode-actor-connectnode-disconnect.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that AudioNodeActor#connectNode() and AudioNodeActor#disconnect() work.
+ * Uses the editor front as the actors do not retain connect state.
+ */
+
+function spawnTest() {
+  let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
+  let { panelWin } = panel;
+  let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
+
+  reload(target);
+
+  let [actors] = yield Promise.all([
+    get3(gFront, "create-node"),
+    waitForGraphRendered(panelWin, 3, 2)
+  ]);
+
+  let [dest, osc, gain] = actors;
+
+  info("Disconnecting oscillator...");
+  osc.disconnect();
+  yield Promise.all([
+    waitForGraphRendered(panelWin, 3, 1),
+    once(gAudioNodes, "disconnect")
+  ]);
+  ok(true, "Oscillator disconnected, event emitted.");
+
+
+  info("Reconnecting oscillator...");
+  osc.connectNode(gain);
+  yield Promise.all([
+    waitForGraphRendered(panelWin, 3, 2),
+    once(gAudioNodes, "connect")
+  ]);
+  ok(true, "Oscillator reconnected.");
+
+
+  yield teardown(panel);
+  finish();
+}
+
--- a/browser/locales/en-US/chrome/browser/aboutDialog.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutDialog.dtd
@@ -33,20 +33,23 @@
 <!ENTITY community.start2           "&brandShortName; is designed by ">
 <!-- LOCALIZATION NOTE (community.mozillaLink): This is a link title that links to http://www.mozilla.org/. -->
 <!ENTITY community.mozillaLink      "&vendorShortName;">
 <!ENTITY community.middle2          ", a ">
 <!-- LOCALIZATION NOTE (community.creditsLink): This is a link title that links to about:credits. -->
 <!ENTITY community.creditsLink      "global community">
 <!ENTITY community.end3             " working together to keep the Web open, public and accessible to all.">
 
-<!ENTITY contribute.start           "Sound interesting? ">
-<!-- LOCALIZATION NOTE (contribute.getInvolvedLink): This is a link title that links to http://www.mozilla.org/contribute/. -->
-<!ENTITY contribute.getInvolvedLink "Get involved!">
-<!ENTITY contribute.end             "">
+<!ENTITY helpus.start               "Want to help? ">
+<!-- LOCALIZATION NOTE (helpus.donateLink): This is a link title that links to https://sendto.mozilla.org/page/contribute/Give-Now?source=mozillaorg_default_footer&ref=firefox_about&utm_campaign=firefox_about&utm_source=firefox&utm_medium=referral&utm_content=20140929_FireFoxAbout. -->
+<!ENTITY helpus.donateLink          "Make a donation">
+<!ENTITY helpus.middle              " or ">
+<!-- LOCALIZATION NOTE (helpus.getInvolvedLink): This is a link title that links to http://www.mozilla.org/contribute/. -->
+<!ENTITY helpus.getInvolvedLink     "get involved!">
+<!ENTITY helpus.end                 "">
 
 <!-- LOCALIZATION NOTE (bottomLinks.license): This is a link title that links to about:license. -->
 <!ENTITY bottomLinks.license        "Licensing Information">
 
 <!-- LOCALIZATION NOTE (bottomLinks.rights): This is a link title that links to about:rights. -->
 <!ENTITY bottomLinks.rights         "End-User Rights">
 
 <!-- LOCALIZATION NOTE (bottomLinks.privacy): This is a link title that links to https://www.mozilla.org/legal/privacy/. -->
--- a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
+++ b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
@@ -92,17 +92,19 @@ email-link-button.tooltiptext3 = Email a
 
 # LOCALIZATION NOTE(quit-button.tooltiptext.linux2): %1$S is the brand name (e.g. Firefox),
 # %2$S is the keyboard shortcut
 quit-button.tooltiptext.linux2 = Quit %1$S (%2$S)
 # LOCALIZATION NOTE(quit-button.tooltiptext.mac): %1$S is the brand name (e.g. Firefox),
 # %2$S is the keyboard shortcut
 quit-button.tooltiptext.mac = Quit %1$S (%2$S)
 
-loop-call-button2.label = Start a conversation
+# LOCALIZATION NOTE(loop-call-button2.label2): This is a brand name, request
+# approval before you change it.
+loop-call-button3.label = Hello
 loop-call-button2.tooltiptext = Start a conversation
 
 social-share-button.label = Share This Page
 social-share-button.tooltiptext = Share This Page
 
 panic-button.label = Forget
 panic-button.tooltiptext = Forget about some browsing history
 
--- a/browser/modules/E10SUtils.jsm
+++ b/browser/modules/E10SUtils.jsm
@@ -14,17 +14,18 @@ this.E10SUtils = {
   shouldBrowserBeRemote: function(aURL) {
     // loadURI in browser.xml treats null as about:blank
     if (!aURL)
       aURL = "about:blank";
 
     if (aURL.startsWith("about:") &&
         aURL.toLowerCase() != "about:home" &&
         aURL.toLowerCase() != "about:blank" &&
-        !aURL.toLowerCase().startsWith("about:neterror")) {
+        !aURL.toLowerCase().startsWith("about:neterror") &&
+        !aURL.toLowerCase().startsWith("about:certerror")) {
       return false;
     }
 
     return true;
   },
 
   shouldLoadURI: function(aDocShell, aURI, aReferrer) {
     // about:blank is the initial document and can load anywhere
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -21,16 +21,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
   "resource://gre/modules/UITelemetry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
   "resource:///modules/BrowserUITelemetry.jsm");
 
 
 const UITOUR_PERMISSION   = "uitour";
+const PREF_TEST_WHITELIST = "browser.uitour.testingOrigins";
 const PREF_SEENPAGEIDS    = "browser.uitour.seenPageIDs";
 const MAX_BUTTONS         = 4;
 
 const BUCKET_NAME         = "UITour";
 const BUCKET_TIMESTEPS    = [
   1 * 60 * 1000, // Until 1 minute after tab is closed/inactive.
   3 * 60 * 1000, // Until 3 minutes after tab is closed/inactive.
   10 * 60 * 1000, // Until 10 minutes after tab is closed/inactive.
@@ -615,30 +616,52 @@ this.UITour = {
                            .getInterface(Ci.nsIWebNavigation)
                            .QueryInterface(Ci.nsIDocShellTreeItem)
                            .rootTreeItem
                            .QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindow)
                            .wrappedJSObject;
   },
 
+  isTestingOrigin: function(aURI) {
+    if (Services.prefs.getPrefType(PREF_TEST_WHITELIST) != Services.prefs.PREF_STRING) {
+      return false;
+    }
+
+    // Add any testing origins (comma-seperated) to the whitelist for the session.
+    for (let origin of Services.prefs.getCharPref(PREF_TEST_WHITELIST).split(",")) {
+      try {
+        let testingURI = Services.io.newURI(origin, null, null);
+        if (aURI.prePath == testingURI.prePath) {
+          return true;
+        }
+      } catch (ex) {
+        Cu.reportError(ex);
+      }
+    }
+    return false;
+  },
+
   ensureTrustedOrigin: function(aDocument) {
     if (aDocument.defaultView.top != aDocument.defaultView)
       return false;
 
     let uri = aDocument.documentURIObject;
 
     if (uri.schemeIs("chrome"))
       return true;
 
     if (!this.isSafeScheme(uri))
       return false;
 
     let permission = Services.perms.testPermission(uri, UITOUR_PERMISSION);
-    return permission == Services.perms.ALLOW_ACTION;
+    if (permission == Services.perms.ALLOW_ACTION)
+      return true;
+
+    return this.isTestingOrigin(uri);
   },
 
   isSafeScheme: function(aURI) {
     let allowedSchemes = new Set(["https", "about"]);
     if (!Services.prefs.getBoolPref("browser.uitour.requireSecure"))
       allowedSchemes.add("http");
 
     if (!allowedSchemes.has(aURI.scheme))
--- a/browser/modules/test/browser_UITour.js
+++ b/browser/modules/test/browser_UITour.js
@@ -20,16 +20,33 @@ let tests = [
       ise(bookmarksMenu.open, false, "Bookmark menu should initially be closed");
 
       gContentAPI.showMenu("bookmarks");
       ise(bookmarksMenu.open, false, "Bookmark menu should not open on a untrusted host");
 
       done();
     }, "http://mochi.test:8888/");
   },
+  function test_testing_host(done) {
+    // Add two testing origins intentionally surrounded by whitespace to be ignored.
+    Services.prefs.setCharPref("browser.uitour.testingOrigins",
+                               "https://test1.example.com, https://test2.example.com:443 ");
+
+    registerCleanupFunction(() => {
+      Services.prefs.clearUserPref("browser.uitour.testingOrigins");
+    });
+    function callback(result) {
+      ok(result, "Callback should be called on a testing origin");
+      done();
+    }
+
+    loadUITourTestPage(function() {
+      gContentAPI.getConfiguration("appinfo", callback);
+    }, "https://test2.example.com/");
+  },
   function test_unsecure_host(done) {
     loadUITourTestPage(function() {
       let bookmarksMenu = document.getElementById("bookmarks-menu-button");
       ise(bookmarksMenu.open, false, "Bookmark menu should initially be closed");
 
       gContentAPI.showMenu("bookmarks");
       ise(bookmarksMenu.open, false, "Bookmark menu should not open on a unsecure host");
 
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/devtools/performance.css
@@ -0,0 +1,5 @@
+/* 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/. */
+
+%include ../../shared/devtools/performance.inc.css
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -247,16 +247,17 @@ browser.jar:
   skin/classic/browser/devtools/breadcrumbs-divider@2x.png      (../shared/devtools/images/breadcrumbs-divider@2x.png)
   skin/classic/browser/devtools/breadcrumbs-scrollbutton.png    (../shared/devtools/images/breadcrumbs-scrollbutton.png)
   skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
 * skin/classic/browser/devtools/canvasdebugger.css    (devtools/canvasdebugger.css)
 * skin/classic/browser/devtools/debugger.css          (devtools/debugger.css)
   skin/classic/browser/devtools/eyedropper.css        (../shared/devtools/eyedropper.css)
 * skin/classic/browser/devtools/netmonitor.css        (devtools/netmonitor.css)
 * skin/classic/browser/devtools/profiler.css          (devtools/profiler.css)
+* skin/classic/browser/devtools/performance.css       (devtools/performance.css)
 * skin/classic/browser/devtools/timeline.css          (devtools/timeline.css)
 * skin/classic/browser/devtools/scratchpad.css        (devtools/scratchpad.css)
 * skin/classic/browser/devtools/shadereditor.css      (devtools/shadereditor.css)
 * skin/classic/browser/devtools/splitview.css         (../shared/devtools/splitview.css)
   skin/classic/browser/devtools/styleeditor.css       (../shared/devtools/styleeditor.css)
   skin/classic/browser/devtools/storage.css           (../shared/devtools/storage.css)
 * skin/classic/browser/devtools/webaudioeditor.css    (devtools/webaudioeditor.css)
   skin/classic/browser/devtools/magnifying-glass.png        (../shared/devtools/images/magnifying-glass.png)
new file mode 100644
--- /dev/null
+++ b/browser/themes/osx/devtools/performance.css
@@ -0,0 +1,6 @@
+/* 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/. */
+
+%include ../shared.inc
+%include ../../shared/devtools/performance.inc.css
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -377,16 +377,17 @@ browser.jar:
   skin/classic/browser/devtools/breadcrumbs-divider@2x.png      (../shared/devtools/images/breadcrumbs-divider@2x.png)
   skin/classic/browser/devtools/breadcrumbs-scrollbutton.png    (../shared/devtools/images/breadcrumbs-scrollbutton.png)
   skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
 * skin/classic/browser/devtools/canvasdebugger.css          (devtools/canvasdebugger.css)
 * skin/classic/browser/devtools/debugger.css                (devtools/debugger.css)
   skin/classic/browser/devtools/eyedropper.css              (../shared/devtools/eyedropper.css)
 * skin/classic/browser/devtools/netmonitor.css              (devtools/netmonitor.css)
 * skin/classic/browser/devtools/profiler.css                (devtools/profiler.css)
+* skin/classic/browser/devtools/performance.css             (devtools/performance.css)
 * skin/classic/browser/devtools/timeline.css                (devtools/timeline.css)
 * skin/classic/browser/devtools/scratchpad.css              (devtools/scratchpad.css)
 * skin/classic/browser/devtools/shadereditor.css            (devtools/shadereditor.css)
 * skin/classic/browser/devtools/splitview.css               (../shared/devtools/splitview.css)
   skin/classic/browser/devtools/styleeditor.css             (../shared/devtools/styleeditor.css)
   skin/classic/browser/devtools/storage.css                 (../shared/devtools/storage.css)
 * skin/classic/browser/devtools/webaudioeditor.css          (devtools/webaudioeditor.css)
   skin/classic/browser/devtools/magnifying-glass.png        (../shared/devtools/images/magnifying-glass.png)
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/devtools/performance.inc.css
@@ -0,0 +1,34 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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/. */
+
+/* Toolbar */
+
+#performance-toolbar {
+  -moz-border-end: 1px solid;
+}
+
+.theme-dark #performance-toolbar > tabs,
+.theme-dark #performance-toolbar {
+  -moz-border-end-color: #000; /* Splitters */
+}
+
+.theme-light #performance-toolbar > tabs,
+.theme-light #performance-toolbar {
+  -moz-border-end-color: #aaa; /* Splitters */
+}
+
+/* Overview Panel */
+
+#record-button {
+  list-style-image: url(profiler-stopwatch.svg);
+}
+
+#record-button[checked] {
+  list-style-image: url(profiler-stopwatch-checked.svg);
+}
+
+#record-button[locked] {
+  pointer-events: none;
+}
new file mode 100644
--- /dev/null
+++ b/browser/themes/windows/devtools/performance.css
@@ -0,0 +1,5 @@
+/* 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/. */
+
+%include ../../shared/devtools/performance.inc.css
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -284,16 +284,17 @@ browser.jar:
         skin/classic/browser/devtools/breadcrumbs-divider@2x.png    (../shared/devtools/images/breadcrumbs-divider@2x.png)
         skin/classic/browser/devtools/breadcrumbs-scrollbutton.png  (../shared/devtools/images/breadcrumbs-scrollbutton.png)
         skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
         skin/classic/browser/devtools/eyedropper.css                (../shared/devtools/eyedropper.css)
 *       skin/classic/browser/devtools/canvasdebugger.css            (devtools/canvasdebugger.css)
 *       skin/classic/browser/devtools/debugger.css                  (devtools/debugger.css)
 *       skin/classic/browser/devtools/netmonitor.css                (devtools/netmonitor.css)
 *       skin/classic/browser/devtools/profiler.css                  (devtools/profiler.css)
+*       skin/classic/browser/devtools/performance.css               (devtools/performance.css)
 *       skin/classic/browser/devtools/timeline.css                  (devtools/timeline.css)
 *       skin/classic/browser/devtools/scratchpad.css                (devtools/scratchpad.css)
 *       skin/classic/browser/devtools/shadereditor.css              (devtools/shadereditor.css)
         skin/classic/browser/devtools/storage.css                   (../shared/devtools/storage.css)
 *       skin/classic/browser/devtools/splitview.css                 (../shared/devtools/splitview.css)
         skin/classic/browser/devtools/styleeditor.css               (../shared/devtools/styleeditor.css)
 *       skin/classic/browser/devtools/webaudioeditor.css            (devtools/webaudioeditor.css)
         skin/classic/browser/devtools/magnifying-glass.png          (../shared/devtools/images/magnifying-glass.png)
--- a/configure.in
+++ b/configure.in
@@ -7706,16 +7706,29 @@ fi
 
 if test "$MOZ_CHROME_FILE_FORMAT" != "jar" &&
     test "$MOZ_CHROME_FILE_FORMAT" != "flat" &&
     test "$MOZ_CHROME_FILE_FORMAT" != "omni"; then
     AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, or omni])
 fi
 
 dnl =========================================================
+dnl Enable support for revamped devtools Performance Tools
+dnl =========================================================
+
+MOZ_ARG_ENABLE_BOOL(devtools-perf,
+[  --enable-devtools-perf Set compile flags necessary for compiling devtools perftools],
+MOZ_DEVTOOLS_PERFTOOLS=1,
+MOZ_DEVTOOLS_PERFTOOLS= )
+if test -n "$MOZ_DEVTOOLS_PERFTOOLS"; then
+  AC_DEFINE(MOZ_DEVTOOLS_PERFTOOLS)
+fi
+AC_SUBST(MOZ_DEVTOOLS_PERFTOOLS)
+
+dnl =========================================================
 dnl Omnijar packaging (bug 552121)
 dnl =========================================================
 dnl Omnijar packaging is compatible with flat packaging.
 dnl In unpackaged builds, omnijar looks for files as if
 dnl things were flat packaged. After packaging, all files
 dnl are loaded from a single jar. MOZ_CHROME_FILE_FORMAT
 dnl is set to flat since putting files into jars is only
 dnl done during packaging with omnijar.
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -16,17 +16,19 @@
 #include "nsIScrollable.h"
 #include "nsITextScroll.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIDOMStorageManager.h"
 #include "nsDocLoader.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "GeckoProfiler.h"
+#ifdef MOZ_ENABLE_PROFILER_SPS
 #include "ProfilerMarkers.h"
+#endif
 
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 
@@ -946,16 +948,18 @@ private:
     nsTObserverArray<nsWeakPtr> mReflowObservers;
     nsTObserverArray<nsWeakPtr> mScrollObservers;
     nsCString         mOriginalUriString;
     nsWeakPtr mOpener;
     nsWeakPtr mOpenedRemote;
 
     // Storing profile timeline markers and if/when recording started
     mozilla::TimeStamp mProfileTimelineStartTime;
+
+#ifdef MOZ_ENABLE_PROFILER_SPS
     struct InternalProfileTimelineMarker
     {
       InternalProfileTimelineMarker(const char* aName,
                                     ProfilerMarkerTracing* aPayload,
                                     float aTime)
         : mName(aName)
         , mPayload(aPayload)
         , mTime(aTime)
@@ -966,16 +970,17 @@ private:
         delete mPayload;
       }
 
       const char* mName;
       ProfilerMarkerTracing* mPayload;
       float mTime;
     };
     nsTArray<InternalProfileTimelineMarker*> mProfileTimelineMarkers;
+#endif
 
     // Get the elapsed time (in millis) since the profile timeline recording
     // started
     float GetProfileTimelineDelta();
 
     // Get rid of all the timeline markers accumulated so far
     void ClearProfileTimelineMarkers();
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1210,26 +1210,28 @@ CreateDependentString(MacroAssembler &ma
     masm.branchTest32(Assembler::NonZero, temp1, temp1, &nonEmpty);
     masm.movePtr(ImmGCPtr(names.empty), string);
     masm.jump(&done);
 
     masm.bind(&nonEmpty);
 
     Label notInline;
 
-    int32_t maxInlineLength =
-        latin1 ? JSFatInlineString::MAX_LENGTH_LATIN1 : JSFatInlineString::MAX_LENGTH_TWO_BYTE;
+    int32_t maxInlineLength = latin1
+                              ? (int32_t) JSFatInlineString::MAX_LENGTH_LATIN1
+                              : (int32_t) JSFatInlineString::MAX_LENGTH_TWO_BYTE;
     masm.branch32(Assembler::Above, temp1, Imm32(maxInlineLength), &notInline);
 
     {
         // Make a normal or fat inline string.
         Label stringAllocated, fatInline;
 
-        int32_t maxNormalInlineLength =
-            latin1 ? JSInlineString::MAX_LENGTH_LATIN1 : JSInlineString::MAX_LENGTH_TWO_BYTE;
+        int32_t maxNormalInlineLength = latin1
+                                        ? (int32_t) JSInlineString::MAX_LENGTH_LATIN1
+                                        : (int32_t) JSInlineString::MAX_LENGTH_TWO_BYTE;
         masm.branch32(Assembler::Above, temp1, Imm32(maxNormalInlineLength), &fatInline);
 
         int32_t normalFlags = (latin1 ? JSString::LATIN1_CHARS_BIT : 0) | JSString::INIT_INLINE_FLAGS;
         masm.newGCString(string, temp2, failure);
         masm.store32(Imm32(normalFlags), Address(string, JSString::offsetOfFlags()));
         masm.jump(&stringAllocated);
 
         masm.bind(&fatInline);
--- a/mobile/android/base/ChromeCast.java
+++ b/mobile/android/base/ChromeCast.java
@@ -32,17 +32,17 @@ import android.content.Context;
 import android.os.Bundle;
 import android.support.v7.media.MediaRouter.RouteInfo;
 import android.util.Log;
 
 /* Implementation of GeckoMediaPlayer for talking to ChromeCast devices */
 class ChromeCast implements GeckoMediaPlayer {
     private static final boolean SHOW_DEBUG = false;
 
-    static final String MIRROR_RECIEVER_APP_ID = "5F72F863";
+    static final String MIRROR_RECEIVER_APP_ID = "5F72F863";
 
     private final Context context;
     private final RouteInfo route;
     private GoogleApiClient apiClient;
     private RemoteMediaPlayer remoteMediaPlayer;
     private final boolean canMirror;
     private String mSessionId;
     private MirrorChannel mMirrorChannel;
@@ -142,17 +142,17 @@ class ChromeCast implements GeckoMediaPl
     public ChromeCast(Context context, RouteInfo route) {
         int status =  GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
         if (status != ConnectionResult.SUCCESS) {
             throw new IllegalStateException("Play services are required for Chromecast support (go status code " + status + ")");
         }
 
         this.context = context;
         this.route = route;
-        this.canMirror = route.supportsControlCategory(CastMediaControlIntent.categoryForCast(MIRROR_RECIEVER_APP_ID));
+        this.canMirror = route.supportsControlCategory(CastMediaControlIntent.categoryForCast(MIRROR_RECEIVER_APP_ID));
     }
 
     // This dumps everything we can find about the device into JSON. This will hopefully make it
     // easier to filter out duplicate devices from different sources in js.
     @Override
     public JSONObject toJSON() {
         final JSONObject obj = new JSONObject();
         try {
@@ -448,17 +448,17 @@ class ChromeCast implements GeckoMediaPl
                     public void onConnected(Bundle connectionHint) {
                         // Sometimes apiClient is null here. See bug 1061032
                         if (apiClient == null || !apiClient.isConnected()) {
                             return;
                         }
 
                         // Launch the media player app and launch this url once its loaded
                         try {
-                            Cast.CastApi.launchApplication(apiClient, MIRROR_RECIEVER_APP_ID, true)
+                            Cast.CastApi.launchApplication(apiClient, MIRROR_RECEIVER_APP_ID, true)
                                 .setResultCallback(new MirrorCallback(callback));
                         } catch (Exception e) {
                             debug("Failed to launch application", e);
                         }
                     }
 
                     @Override
                     public void onConnectionSuspended(int cause) {
--- a/mobile/android/base/ContactService.java
+++ b/mobile/android/base/ContactService.java
@@ -115,17 +115,17 @@ public class ContactService implements G
             "Android:Contacts:GetCount",
             "Android:Contact:Remove",
             "Android:Contact:Save");
     }
 
     @Override
     public void handleMessage(final String event, final JSONObject message) {
         // If the account chooser dialog needs shown to the user, the message handling becomes
-        // asychronous so it needs posted to a background thread from the UI thread when the
+        // asynchronous so it needs posted to a background thread from the UI thread when the
         // account chooser dialog is dismissed by the user.
         Runnable handleMessage = new Runnable() {
             @Override
             public void run() {
                 try {
                     if (DEBUG) {
                         Log.d(LOGTAG, "Event: " + event + "\nMessage: " + message.toString(3));
                     }
@@ -1019,17 +1019,17 @@ public class ContactService implements G
         // Why is updating a contact so weird and horribly inefficient? Because Android doesn't
         // like multiple values for contact fields, but the Mozilla contacts API calls for this.
         // This means the Android update function is essentially completely useless. Why not just
         // delete the contact and re-insert it? Because that would change the contact ID and the
         // Mozilla contacts API shouldn't have this behavior. The solution is to delete each
         // row from the contacts data table that belongs to the contact, and insert the new
         // fields. But then why not just delete all the data from the data in one go and
         // insert the new data in another? Because if all the data relating to a contact is
-        // deleted, Android will "conviently" remove the ID making it impossible to insert data
+        // deleted, Android will "conveniently" remove the ID making it impossible to insert data
         // under the old ID. To work around this, we put a Mozilla contact flag in the database
 
         ContentProviderOperation removeOptions = ContentProviderOperation.newDelete(Data.CONTENT_URI)
                                                  .withSelection(Data.RAW_CONTACT_ID + "=? AND " +
                                                  Data.MIMETYPE + " != '" + MIMETYPE_MOZILLA_CONTACTS_FLAG + "'",
                                                  new String[] {String.valueOf(rawContactId)})
                                                  .build();
 
@@ -1963,19 +1963,19 @@ public class ContactService implements G
         }
         mEmailTypesMap = new HashMap<String, Integer>();
 
         mEmailTypesMap.put("home", Email.TYPE_HOME);
         mEmailTypesMap.put("mobile", Email.TYPE_MOBILE);
         mEmailTypesMap.put("work", Email.TYPE_WORK);
     }
 
-    private int getWebsiteType(String webisteType) {
+    private int getWebsiteType(String websiteType) {
         initWebsiteTypesMap();
-        Integer type = mWebsiteTypesMap.get(webisteType.toLowerCase());
+        Integer type = mWebsiteTypesMap.get(websiteType.toLowerCase());
         return type != null ? type : Website.TYPE_CUSTOM;
     }
 
     private void initWebsiteTypesMap() {
         if (mWebsiteTypesMap != null) {
             return;
         }
         mWebsiteTypesMap = new HashMap<String, Integer>();
--- a/mobile/android/base/DoorHangerPopup.java
+++ b/mobile/android/base/DoorHangerPopup.java
@@ -179,17 +179,17 @@ public class DoorHangerPopup extends Arr
             } catch (JSONException e) {
                 Log.e(LOGTAG, "Error creating doorhanger button", e);
             }
         }
 
         mDoorHangers.add(newDoorHanger);
         mContent.addView(newDoorHanger);
 
-        // Only update the popup if we're adding a notifcation to the selected tab
+        // Only update the popup if we're adding a notification to the selected tab
         if (tabId == Tabs.getInstance().getSelectedTab().getId())
             updatePopup();
     }
 
 
     /*
      * DoorHanger.OnButtonClickListener implementation
      */
--- a/mobile/android/base/EditBookmarkDialog.java
+++ b/mobile/android/base/EditBookmarkDialog.java
@@ -49,20 +49,20 @@ public class EditBookmarkDialog {
             title = aTitle;
             url = aUrl;
             keyword = aKeyword;
         }
     }
 
     /**
      * This text watcher to enable or disable the OK button if the dialog contains
-     * valid information. This class is overridden to do data checking diffferent fields.
+     * valid information. This class is overridden to do data checking on different fields.
      * By itself, it always enables the button.
      *
-     * Callers can also assing a paired partner to the TextWatcher, and callers will check
+     * Callers can also assign a paired partner to the TextWatcher, and callers will check
      * that both are enabled before enabling the ok button.
      */
     private class EditBookmarkTextWatcher implements TextWatcher {
         // A stored reference to the dialog containing the text field being watched
         protected AlertDialog mDialog;
 
         // A stored text watcher to do the real verification of a field
         protected EditBookmarkTextWatcher mPairedTextWatcher;
--- a/mobile/android/base/FilePicker.java
+++ b/mobile/android/base/FilePicker.java
@@ -95,17 +95,17 @@ public class FilePicker implements Gecko
         intent.setType(mimeType);
         intent.addCategory(Intent.CATEGORY_OPENABLE);
         return intent;
     }
 
     private List<Intent> getIntentsForFilePicker(final String mimeType,
                                                        final FilePickerResultHandler fileHandler) {
         // The base intent to use for the file picker. Even if this is an implicit intent, Android will
-        // still show a list of Activitiees that match this action/type.
+        // still show a list of Activities that match this action/type.
         Intent baseIntent;
         // A HashMap of Activities the base intent will show in the chooser. This is used
         // to filter activities from other intents so that we don't show duplicates.
         HashMap<String, Intent> baseIntents = new HashMap<String, Intent>();
         // A list of other activities to shwo in the picker (and the intents to launch them).
         HashMap<String, Intent> intents = new HashMap<String, Intent> ();
 
         if ("audio/*".equals(mimeType)) {
--- a/mobile/android/base/GeckoBatteryManager.java
+++ b/mobile/android/base/GeckoBatteryManager.java
@@ -79,17 +79,17 @@ public class GeckoBatteryManager extends
         }
 
         boolean previousCharging = isCharging();
         double previousLevel = getLevel();
 
         // NOTE: it might not be common (in 2012) but technically, Android can run
         // on a device that has no battery so we want to make sure it's not the case
         // before bothering checking for battery state.
-        // However, the Galaxy Nexus phone advertizes itself as battery-less which
+        // However, the Galaxy Nexus phone advertises itself as battery-less which
         // force us to special-case the logic.
         // See the Google bug: https://code.google.com/p/android/issues/detail?id=22035
         if (intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false) ||
                 Build.MODEL.equals("Galaxy Nexus")) {
             int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
             if (plugged == -1) {
                 sCharging = kDefaultCharging;
                 Log.e(LOGTAG, "Failed to get the plugged status!");
--- a/mobile/android/base/GeckoEditable.java
+++ b/mobile/android/base/GeckoEditable.java
@@ -253,19 +253,19 @@ final class GeckoEditable
         private KeyEvent [] synthesizeKeyEvents(CharSequence cs) {
             try {
                 if (mKeyMap == null) {
                     mKeyMap = KeyCharacterMap.load(
                         Versions.preHC ? KeyCharacterMap.ALPHA :
                                          KeyCharacterMap.VIRTUAL_KEYBOARD);
                 }
             } catch (Exception e) {
-                // KeyCharacterMap.UnavailableExcepton is not found on Gingerbread;
+                // KeyCharacterMap.UnavailableException is not found on Gingerbread;
                 // besides, it seems like HC and ICS will throw something other than
-                // KeyCharacterMap.UnavailableExcepton; so use a generic Exception here
+                // KeyCharacterMap.UnavailableException; so use a generic Exception here
                 return null;
             }
             KeyEvent [] keyEvents = mKeyMap.getEvents(cs.toString().toCharArray());
             if (keyEvents == null || keyEvents.length == 0) {
                 return null;
             }
             return keyEvents;
         }
--- a/mobile/android/base/GeckoScreenOrientation.java
+++ b/mobile/android/base/GeckoScreenOrientation.java
@@ -285,17 +285,17 @@ public class GeckoScreenOrientation {
         }
 
         // We don't support multiple orientations yet. To avoid developer
         // confusion, just take the first one listed.
         return screenOrientationFromString(orientations.get(0));
     }
 
     /*
-     * Retrieve the scren orientation from a string.
+     * Retrieve the screen orientation from a string.
      *
      * @param aStr
      *        String hopefully containing a screen orientation name.
      * @return Gecko screen orientation if matched, DEFAULT_SCREEN_ORIENTATION
      *         otherwise.
      */
     public static ScreenOrientation screenOrientationFromString(String aStr) {
         switch (aStr) {
--- a/mobile/android/base/GeckoSmsManager.java
+++ b/mobile/android/base/GeckoSmsManager.java
@@ -465,17 +465,17 @@ public class GeckoSmsManager
           int id = saveSentMessage(number, message, timestamp);
 
           notifySmsSent(id, number, message, timestamp,
                         bundle.getInt("requestId"));
 
           envelope.setMessageId(id);
           envelope.setMessageTimestamp(timestamp);
 
-          Log.i("GeckoSmsManager", "SMS sending was successfull!");
+          Log.i("GeckoSmsManager", "SMS sending was successful!");
         } else {
           notifySmsDelivery(envelope.getMessageId(),
                             kDeliveryStatusSuccess,
                             bundle.getString("number"),
                             bundle.getString("message"),
                             envelope.getMessageTimestamp());
           Log.i("GeckoSmsManager", "SMS successfully delivered!");
         }
--- a/mobile/android/base/GeckoView.java
+++ b/mobile/android/base/GeckoView.java
@@ -656,37 +656,37 @@ public class GeckoView extends LayerView
         * @param url The resource being loaded.
         */
         public void onPageStart(GeckoView view, GeckoView.Browser browser, String url);
     
         /**
         * A Browser has finished loading content from the network.
         * @param view The GeckoView that initiated the callback.
         * @param browser The Browser that was loading the content.
-        * @param success Whether the page loaded successfully or an error occured.
+        * @param success Whether the page loaded successfully or an error occurred.
         */
         public void onPageStop(GeckoView view, GeckoView.Browser browser, boolean success);
-    
+
         /**
         * A Browser is displaying content. This page could have been loaded via
         * network or from the session history.
         * @param view The GeckoView that initiated the callback.
         * @param browser The Browser that is showing the content.
         */
         public void onPageShow(GeckoView view, GeckoView.Browser browser);
-    
+
         /**
         * A page title was discovered in the content or updated after the content
         * loaded.
         * @param view The GeckoView that initiated the callback.
         * @param browser The Browser that is showing the content.
         * @param title The title sent from the content.
         */
         public void onReceivedTitle(GeckoView view, GeckoView.Browser browser, String title);
-    
+
         /**
         * A link element was discovered in the content or updated after the content
         * loaded that specifies a favicon.
         * @param view The GeckoView that initiated the callback.
         * @param browser The Browser that is showing the content.
         * @param url The href of the link element specifying the favicon.
         * @param size The maximum size specified for the favicon, or -1 for any size.
         */
--- a/mobile/android/base/GeckoViewContent.java
+++ b/mobile/android/base/GeckoViewContent.java
@@ -14,17 +14,17 @@ public class GeckoViewContent implements
     */
     @Override
     public void onPageStart(GeckoView view, GeckoView.Browser browser, String url) {}
 
     /**
     * A Browser has finished loading content from the network.
     * @param view The GeckoView that initiated the callback.
     * @param browser The Browser that was loading the content.
-    * @param success Whether the page loaded successfully or an error occured.
+    * @param success Whether the page loaded successfully or an error occurred.
     */
     @Override
     public void onPageStop(GeckoView view, GeckoView.Browser browser, boolean success) {}
 
     /**
     * A Browser is displaying content. This page could have been loaded via
     * network or from the session history.
     * @param view The GeckoView that initiated the callback.
--- a/mobile/android/base/JavaAddonManager.java
+++ b/mobile/android/base/JavaAddonManager.java
@@ -34,17 +34,17 @@ import java.util.Map;
  * are registered as event listeners. If no such constructor exists, the default
  * constructor is invoked instead.
  *
  * Note: The Map and Handler.Callback classes were used in this API definition
  * rather than defining a custom class. This was done explicitly so that the
  * addon code can be compiled against the android.jar provided in the Android
  * SDK, rather than having to be compiled against Fennec source code.
  *
- * The Handler.Callback instances provided (as described above) are inovked with
+ * The Handler.Callback instances provided (as described above) are invoked with
  * Message objects when the corresponding events are dispatched. The Bundle
  * object attached to the Message will contain the "primitive" values from the
  * JSON of the event. ("primitive" includes bool/int/long/double/String). If
  * the addon callback wishes to synchronously return a value back to the event
  * dispatcher, they can do so by inserting the response string into the bundle
  * under the key "response".
  */
 class JavaAddonManager implements GeckoEventListener {
--- a/mobile/android/base/MediaPlayerManager.java
+++ b/mobile/android/base/MediaPlayerManager.java
@@ -235,17 +235,17 @@ class MediaPlayerManager implements Nati
         mediaRouter.removeCallback(callback);
     }
 
     @Override
     public void onResume() {
         MediaRouteSelector selectorBuilder = new MediaRouteSelector.Builder()
             .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
             .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
-            .addControlCategory(CastMediaControlIntent.categoryForCast(ChromeCast.MIRROR_RECIEVER_APP_ID))
+            .addControlCategory(CastMediaControlIntent.categoryForCast(ChromeCast.MIRROR_RECEIVER_APP_ID))
             .build();
         mediaRouter.addCallback(selectorBuilder, callback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
     }
 
     @Override
     public void onOrientationChanged() { }
 
 }
--- a/mobile/android/base/SharedPreferencesHelper.java
+++ b/mobile/android/base/SharedPreferencesHelper.java
@@ -219,17 +219,17 @@ public final class SharedPreferencesHelp
             }
             try {
                 final JSONObject msg = new JSONObject();
                 msg.put("scope", this.scope.key);
                 msg.put("branch", this.branch);
                 msg.put("profileName", this.profileName);
                 msg.put("key", key);
 
-                // Truly, this is awful, but the API impedence is strong: there
+                // Truly, this is awful, but the API impedance is strong: there
                 // is no way to get a single untyped value from a
                 // SharedPreferences instance.
                 msg.put("value", sharedPreferences.getAll().get(key));
 
                 GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SharedPreferences:Changed", msg.toString()));
             } catch (JSONException e) {
                 Log.e(LOGTAG, "Got exception creating JSON object", e);
                 return;
--- a/mobile/android/base/TextSelection.java
+++ b/mobile/android/base/TextSelection.java
@@ -47,18 +47,18 @@ class TextSelection extends Layer implem
     private float mViewLeft;
     private float mViewTop;
     private float mViewZoom;
 
     private String mCurrentItems;
 
     private TextSelectionActionModeCallback mCallback;
 
-    // These timers are used to avoid flicker caused by selection handles showing/hiding quickly. For isntance
-    // when moving between single handle caret mode and two handle selection mode.
+    // These timers are used to avoid flicker caused by selection handles showing/hiding quickly.
+    // For instance when moving between single handle caret mode and two handle selection mode.
     private final Timer mActionModeTimer = new Timer("actionMode");
     private class ActionModeTimerTask extends TimerTask {
         @Override
         public void run() {
             ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
                     endActionMode();
--- a/mobile/android/base/animation/Rotate3DAnimation.java
+++ b/mobile/android/base/animation/Rotate3DAnimation.java
@@ -38,17 +38,17 @@ public class Rotate3DAnimation extends A
     private Camera mCamera;
 
     private int mWidth = 1;
     private int mHeight = 1;
 
     /**
      * Creates a new 3D rotation on the Y axis. The rotation is defined by its
      * start angle and its end angle. Both angles are in degrees. The rotation
-     * is performed around a center point on the 2D space, definied by a pair
+     * is performed around a center point on the 2D space, defined by a pair
      * of X and Y coordinates, called centerX and centerY. When the animation
      * starts, a translation on the Z axis (depth) is performed. The length
      * of the translation can be specified, as well as whether the translation
      * should be reversed in time.
      *
      * @param fromDegrees the start angle of the 3D rotation
      * @param toDegrees the end angle of the 3D rotation
      * @param centerX the X center of the 3D rotation
--- a/mobile/android/base/background/fxa/FxAccountUtils.java
+++ b/mobile/android/base/background/fxa/FxAccountUtils.java
@@ -108,17 +108,17 @@ public class FxAccountUtils {
    * We separate this since multiple login-time operations want it, and the
    * PBKDF2 operation is computationally expensive.
    */
   public static byte[] generateQuickStretchedPW(byte[] emailUTF8, byte[] passwordUTF8) throws GeneralSecurityException, UnsupportedEncodingException {
     byte[] S = FxAccountUtils.KWE("quickStretch", emailUTF8);
     try {
       return NativeCrypto.pbkdf2SHA256(passwordUTF8, S, NUMBER_OF_QUICK_STRETCH_ROUNDS, 32);
     } catch (final LinkageError e) {
-      // This will throw UnsatisifiedLinkError (missing mozglue) the first time it is called, and
+      // This will throw UnsatisfiedLinkError (missing mozglue) the first time it is called, and
       // ClassNotDefFoundError, for the uninitialized NativeCrypto class, each subsequent time this
       // is called; LinkageError is their common ancestor.
       Logger.warn(LOG_TAG, "Got throwable stretching password using native pbkdf2SHA256 " +
           "implementation; ignoring and using Java implementation.", e);
       return PBKDF2.pbkdf2SHA256(passwordUTF8, S, NUMBER_OF_QUICK_STRETCH_ROUNDS, 32);
     }
   }
 
--- a/mobile/android/base/background/healthreport/HealthReportBroadcastService.java
+++ b/mobile/android/base/background/healthreport/HealthReportBroadcastService.java
@@ -103,17 +103,17 @@ public class HealthReportBroadcastServic
     // Intent can be null. Bug 1025937.
     if (intent == null) {
       Logger.debug(LOG_TAG, "Short-circuiting on null intent.");
       return;
     }
 
     // The same intent can be handled by multiple methods so do not short-circuit evaluate.
     boolean handled = attemptHandleIntentForUpload(intent);
-    handled = attemptHandleIntentForPrune(intent) ? true : handled;
+    handled = attemptHandleIntentForPrune(intent) || handled;
 
     if (!handled) {
       Logger.warn(LOG_TAG, "Unhandled intent with action " + intent.getAction() + ".");
     }
   }
 
   /**
    * Attempts to handle the given intent for FHR document upload. If it cannot, false is returned.
--- a/mobile/android/base/background/healthreport/HealthReportStorage.java
+++ b/mobile/android/base/background/healthreport/HealthReportStorage.java
@@ -197,17 +197,17 @@ public interface HealthReportStorage {
   public Cursor getEventsSince(long time);
 
   /**
    * Ensure that a measurement and all of its fields are registered with the DB.
    * No fields will be processed if the measurement exists with the specified
    * version.
    *
    * @param measurement
-   *          a measurement name, such as "org.mozila.appInfo.appInfo".
+   *          a measurement name, such as "org.mozilla.appInfo.appInfo".
    * @param version
    *          a version number, such as '3'.
    * @param fields
    *          a {@link MeasurementFields} instance, consisting of a collection
    *          of field names.
    */
   public void ensureMeasurementInitialized(String measurement,
                                            int version,
--- a/mobile/android/base/background/healthreport/prune/PrunePolicy.java
+++ b/mobile/android/base/background/healthreport/prune/PrunePolicy.java
@@ -36,17 +36,17 @@ public class PrunePolicy {
   protected SharedPreferences getSharedPreferences() {
     return this.sharedPreferences;
   }
 
   public void tick(final long time) {
     try {
       try {
         boolean pruned = attemptPruneBySize(time);
-        pruned = attemptExpiration(time) ? true : pruned;
+        pruned = attemptExpiration(time) || pruned;
         // We only need to cleanup after a large pruning.
         if (pruned) {
           attemptStorageCleanup(time);
         }
       } catch (Exception e) {
         // While catching Exception is ordinarily bad form, this Service runs in the same process
         // as Fennec so if we crash, it crashes. Additionally, this Service runs regularly so
         // these crashes could be regular. Thus, we choose to quietly fail instead.
--- a/mobile/android/base/db/BrowserDatabaseHelper.java
+++ b/mobile/android/base/db/BrowserDatabaseHelper.java
@@ -300,17 +300,17 @@ final class BrowserDatabaseHelper extend
                     " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE)  + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED)  + " = 0 AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
                                     " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
                     " UNION ALL" +
                     // History with and without bookmark.
                     " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
-                                 // Prioritze bookmark titles over history titles, since the user may have
+                                 // Prioritize bookmark titles over history titles, since the user may have
                                  // customized the title for a bookmark.
                                  "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
                                                qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
                                  qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
                     " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
                         " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
@@ -355,17 +355,17 @@ final class BrowserDatabaseHelper extend
                     " WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE)  + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED)  + " = 0 AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
                                     " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
                     " UNION ALL" +
                     // History with and without bookmark.
                     " SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
-                                 // Prioritze bookmark titles over history titles, since the user may have
+                                 // Prioritize bookmark titles over history titles, since the user may have
                                  // customized the title for a bookmark.
                                  "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
                                                qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
                                  "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
                                     Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
                                     Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
                                  qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
@@ -414,17 +414,17 @@ final class BrowserDatabaseHelper extend
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED)  + " = 0 AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
                                     " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
                     " UNION ALL" +
                     // History with and without bookmark.
                     " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
                                  qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) +  " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
-                                 // Prioritze bookmark titles over history titles, since the user may have
+                                 // Prioritize bookmark titles over history titles, since the user may have
                                  // customized the title for a bookmark.
                                  "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
                                                qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
                                  "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
                                     Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
                                     Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
                                  qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
@@ -473,17 +473,17 @@ final class BrowserDatabaseHelper extend
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED)  + " = 0 AND " +
                                 qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
                                     " NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
                     " UNION ALL" +
                     // History with and without bookmark.
                     " SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
                                  qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) +  " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
-                                 // Prioritze bookmark titles over history titles, since the user may have
+                                 // Prioritize bookmark titles over history titles, since the user may have
                                  // customized the title for a bookmark.
                                  "COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
                                                qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
                                  qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
                                  qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
                     " FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
                         " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
--- a/mobile/android/base/db/TopSitesCursorWrapper.java
+++ b/mobile/android/base/db/TopSitesCursorWrapper.java
@@ -61,17 +61,17 @@ public class TopSitesCursorWrapper imple
     private Cursor currentCursor;
 
     // The cursor for the top sites query
     private final Cursor topCursor;
 
     // The cursor for the pinned sites query
     private final Cursor pinnedCursor;
 
-    // The cursor for the sugested sites query
+    // The cursor for the suggested sites query
     private final Cursor suggestedCursor;
 
     // Associates pinned sites and their respective positions
     private SparseBooleanArray pinnedPositions;
 
     // Current position of the cursor
     private int currentPosition = -1;
 
--- a/mobile/android/base/docs/localeswitching.rst
+++ b/mobile/android/base/docs/localeswitching.rst
@@ -17,17 +17,17 @@ The user's choice of locale is stored in
 
 ``BrowserLocaleManager`` takes care of updating the active locale when asked to do so. It also manages persistence and retrieval of the locale preference.
 
 The question, then, is when to do so.
 
 Locale events
 =============
 
-One might imagine that we need only set the locale when our Application is instantiated, and when a new locale is set. Alas, that's not the case: whenever there's a configuration change (*e.g.*, screen rotation), when a new activity is started, and at other apparently random times, Android will supply our activities with a configuration that's been reset to the sytem locale.
+One might imagine that we need only set the locale when our Application is instantiated, and when a new locale is set. Alas, that's not the case: whenever there's a configuration change (*e.g.*, screen rotation), when a new activity is started, and at other apparently random times, Android will supply our activities with a configuration that's been reset to the system locale.
 
 For this reason, each starting activity must ask ``BrowserLocaleManager`` to fix its locale.
 
 Ideally, we also need to perform some amount of work when our configuration changes, when our activity is resumed, and perhaps when a result is returned from another activity, if that activity can change the app locale (as is the case for any activity that calls out to ``GeckoPreferences`` -- see ``BrowserApp#onActivityResult``).
 
 ``GeckoApp`` itself does some additional work, because it has particular performance constraints, and also is the typical root of the preferences activity.
 
 Here's an example of the work that a typical activity should do::
--- a/mobile/android/base/fxa/activities/FxAccountConfirmAccountActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountConfirmAccountActivity.java
@@ -136,17 +136,17 @@ public class FxAccountConfirmAccountActi
     case NeedsVerification:
       // This is what we're here to handle.
       break;
     case NeedsPassword:
     case NeedsUpgrade:
     case None:
     default:
       // We're not in the right place!  Redirect to status.
-      Logger.warn(LOG_TAG, "No need to verifiy Firefox Account that needs action " + neededAction.toString() +
+      Logger.warn(LOG_TAG, "No need to verify Firefox Account that needs action " + neededAction.toString() +
           " (in state " + state.getStateLabel() + ").");
       setResult(RESULT_CANCELED);
       this.redirectToActivity(FxAccountStatusActivity.class);
       return;
     }
 
     final String email = fxAccount.getEmail();
     final String text = getResources().getString(R.string.fxaccount_confirm_account_verification_link, email);
--- a/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
+++ b/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
@@ -671,17 +671,17 @@ public class FxAccountStatusFragment
       } else {
         return false;
       }
       return true;
     }
   }
 
   /**
-   * Iterate through debug buttons, adding a special deubg preference click
+   * Iterate through debug buttons, adding a special debug preference click
    * listener to each of them.
    */
   protected void connectDebugButtons() {
     // Separate listener to really separate debug logic from main code paths.
     final OnPreferenceClickListener listener = new DebugPreferenceClickListener();
 
     // We don't want to use Android resource strings for debug UI, so we just
     // use the keys throughout.
--- a/mobile/android/base/fxa/authenticator/AndroidFxAccount.java
+++ b/mobile/android/base/fxa/authenticator/AndroidFxAccount.java
@@ -91,17 +91,17 @@ public class AndroidFxAccount {
     this.accountManager = AccountManager.get(this.context);
   }
 
   /**
    * Persist the Firefox account to disk as a JSON object. Note that this is a wrapper around
    * {@link AccountPickler#pickle}, and is identical to calling it directly.
    * <p>
    * Note that pickling is different from bundling, which involves operations on a
-   * {@link android.os.Bundle Bundle} object of miscellaenous data associated with the account.
+   * {@link android.os.Bundle Bundle} object of miscellaneous data associated with the account.
    * See {@link #persistBundle} and {@link #unbundle} for more.
    */
   public void pickle(final String filename) {
     AccountPickler.pickle(this, filename);
   }
 
   public Account getAndroidAccount() {
     return this.account;
--- a/mobile/android/base/gfx/GLController.java
+++ b/mobile/android/base/gfx/GLController.java
@@ -179,18 +179,18 @@ public class GLController {
         }
 
         if (!AttemptPreallocateEGLSurfaceForCompositor()) {
             return;
         }
 
         // Only try to create the compositor if we have a valid surface and gecko is up. When these
         // two conditions are satisfied, we can be relatively sure that the compositor creation will
-        // happen without needing to block anyhwere. Do it with a sync gecko event so that the
-        // android doesn't have a chance to destroy our surface in between.
+        // happen without needing to block anywhere. Do it with a synchronous Gecko event so that the
+        // Android doesn't have a chance to destroy our surface in between.
         if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
             GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createCompositorCreateEvent(mWidth, mHeight));
         }
     }
 
     void compositorCreated() {
         // This is invoked on the compositor thread, while the java UI thread
         // is blocked on the gecko sync event in updateCompositor() above
@@ -203,17 +203,17 @@ public class GLController {
 
     private void initEGL() {
         if (mEGL != null) {
             return;
         }
 
         // This join() should not be necessary, but makes this code a bit easier to think about.
         // The EGLPreloadingThread should long be done by now, and even if it's not,
-        // it shouldn't be a problem to be initalizing EGL from two different threads.
+        // it shouldn't be a problem to be initializing EGL from two different threads.
         // Still, having this join() here means that we don't have to wonder about what
         // kind of caveats might exist with EGL initialization reentrancy on various drivers.
         try {
             mEGLPreloadingThread.join();
         } catch (InterruptedException e) {
             Log.w(LOGTAG, "EGLPreloadingThread interrupted", e);
         }
 
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -76,18 +76,18 @@ class GeckoLayerClient implements LayerV
     /* The current viewport metrics.
      * This is volatile so that we can read and write to it from different threads.
      * We avoid synchronization to make getting the viewport metrics from
      * the compositor as cheap as possible. The viewport is immutable so
      * we don't need to worry about anyone mutating it while we're reading from it.
      * Specifically:
      * 1) reading mViewportMetrics from any thread is fine without synchronization
      * 2) writing to mViewportMetrics requires synchronizing on the layer controller object
-     * 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in
-     *    case 1 above) you should always frist grab a local copy of the reference, and then use
+     * 3) whenever reading multiple fields from mViewportMetrics without synchronization (i.e. in
+     *    case 1 above) you should always first grab a local copy of the reference, and then use
      *    that because mViewportMetrics might get reassigned in between reading the different
      *    fields. */
     private volatile ImmutableViewportMetrics mViewportMetrics;
     private LayerView.OnMetricsChangedListener mViewportChangeListener;
 
     private ZoomConstraints mZoomConstraints;
 
     private boolean mGeckoIsReady;
@@ -646,17 +646,17 @@ class GeckoLayerClient implements LayerV
         }
     }
 
     /** The compositor invokes this function on every frame to figure out what part of the
       * page to display, and to inform Java of the current display port. Since it is called
       * on every frame, it needs to be ultra-fast.
       * It avoids taking any locks or allocating any objects. We keep around a
       * mCurrentViewTransform so we don't need to allocate a new ViewTransform
-      * everytime we're called. NOTE: we might be able to return a ImmutableViewportMetrics
+      * every time we're called. NOTE: we might be able to return a ImmutableViewportMetrics
       * which would avoid the copy into mCurrentViewTransform.
       */
     @WrapElementForJNI(allowMultithread = true)
     public ViewTransform syncViewportInfo(int x, int y, int width, int height, float resolution, boolean layersUpdated) {
         // getViewportMetrics is thread safe so we don't need to synchronize.
         // We save the viewport metrics here, so we later use it later in
         // createFrame (which will be called by nsWindow::DrawWindowUnderlay on
         // the native side, by the compositor). The viewport
--- a/mobile/android/base/gfx/JavaPanZoomController.java
+++ b/mobile/android/base/gfx/JavaPanZoomController.java
@@ -391,17 +391,17 @@ class JavaPanZoomController
     }
 
     /** This function must be called on the UI thread. */
     public void startingNewEventBlock(MotionEvent event, boolean waitingForTouchListeners) {
         checkMainThread();
         mSubscroller.cancel();
         if (waitingForTouchListeners && (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
             // this is the first touch point going down, so we enter the pending state
-            // seting the state will kill any animations in progress, possibly leaving
+            // setting the state will kill any animations in progress, possibly leaving
             // the page in overscroll
             setState(PanZoomState.WAITING_LISTENERS);
         }
     }
 
     /** This must be called on the UI thread. */
     @Override
     public void pageRectUpdated() {
@@ -1193,17 +1193,17 @@ class JavaPanZoomController
 
         synchronized (mTarget.getLock()) {
             float zoomFactor = getAdjustedZoomFactor(detector.getCurrentSpan() / prevSpan);
             scrollBy(mLastZoomFocus.x - detector.getFocusX(),
                      mLastZoomFocus.y - detector.getFocusY());
             mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
             ImmutableViewportMetrics target = getMetrics().scaleTo(zoomFactor, mLastZoomFocus);
 
-            // If overscroll is diabled, prevent zooming outside the normal document pans.
+            // If overscroll is disabled, prevent zooming outside the normal document pans.
             if (mX.getOverScrollMode() == View.OVER_SCROLL_NEVER || mY.getOverScrollMode() == View.OVER_SCROLL_NEVER) {
                 target = getValidViewportMetrics(target);
             }
             mTarget.setViewportMetrics(target);
         }
 
         GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY, mLastZoomFocus, getMetrics().zoomFactor);
         GeckoAppShell.sendEventToGecko(event);
--- a/mobile/android/base/gfx/LayerMarginsAnimator.java
+++ b/mobile/android/base/gfx/LayerMarginsAnimator.java
@@ -40,17 +40,17 @@ public class LayerMarginsAnimator {
     private LayerMarginsAnimationTask mAnimationTask;
     /* This interpolator is used for the above mentioned animation */
     private final DecelerateInterpolator mInterpolator;
     /* The GeckoLayerClient whose margins will be animated */
     private final GeckoLayerClient mTarget;
     /* The distance that has been scrolled since either the first touch event,
      * or since the margins were last fully hidden */
     private final PointF mTouchTravelDistance;
-    /* The ID of the prefs listener for the show-marginss threshold */
+    /* The ID of the prefs listener for the show-margins threshold */
     private Integer mPrefObserverId;
 
     public LayerMarginsAnimator(GeckoLayerClient aTarget, LayerView aView) {
         // Assign member variables from parameters
         mTarget = aTarget;
 
         // Create other member variables
         mMaxMargins = new RectF();
--- a/mobile/android/base/home/BrowserSearch.java
+++ b/mobile/android/base/home/BrowserSearch.java
@@ -329,17 +329,17 @@ public class BrowserSearch extends HomeF
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
             "SearchEngines:Data");
     }
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        // Intialize the search adapter
+        // Initialize the search adapter
         mAdapter = new SearchAdapter(getActivity());
         mList.setAdapter(mAdapter);
 
         // Only create an instance when we need it
         mSuggestionLoaderCallbacks = null;
 
         // Create callbacks before the initial loader is started
         mCursorLoaderCallbacks = new CursorLoaderCallbacks();
--- a/mobile/android/base/home/HomeConfig.java
+++ b/mobile/android/base/home/HomeConfig.java
@@ -1276,17 +1276,17 @@ public final class HomeConfig {
 
                 mEnabledCount++;
                 if (mEnabledCount == 1 || panelConfig.isDefault()) {
                     setDefault(panelConfig.getId());
                 }
 
                 installed = true;
 
-                // Add an event to the queue if a new panel is sucessfully installed.
+                // Add an event to the queue if a new panel is successfully installed.
                 mEventQueue.add(GeckoEvent.createBroadcastEvent("HomePanels:Installed", panelConfig.getId()));
             }
 
             mHasChanged = true;
             return installed;
         }
 
         /**
@@ -1312,17 +1312,17 @@ public final class HomeConfig {
             if (!panelConfig.isDisabled()) {
                 mEnabledCount--;
             }
 
             if (isCurrentDefaultPanel(panelConfig)) {
                 findNewDefault();
             }
 
-            // Add an event to the queue if a panel is succesfully uninstalled.
+            // Add an event to the queue if a panel is successfully uninstalled.
             mEventQueue.add(GeckoEvent.createBroadcastEvent("HomePanels:Uninstalled", panelId));
 
             mHasChanged = true;
             return true;
         }
 
         /**
          * Moves panel associated with panelId to the specified position.
--- a/mobile/android/base/home/PanelViewAdapter.java
+++ b/mobile/android/base/home/PanelViewAdapter.java
@@ -84,17 +84,17 @@ class PanelViewAdapter extends CursorAda
         }
 
         final Cursor cursor = getCursor(position);
         final PanelItemView item = (PanelItemView) view;
         item.updateFromCursor(cursor);
     }
 
     private boolean isShowingBack() {
-        return (filterManager != null ? filterManager.canGoBack() : false);
+        return filterManager != null && filterManager.canGoBack();
     }
 
     private final Cursor getCursor(int position) {
         final Cursor cursor = getCursor();
         if (cursor == null || !cursor.moveToPosition(position)) {
             throw new IllegalStateException("Couldn't move cursor to position " + position);
         }
 
--- a/mobile/android/base/home/RemoteTabsExpandableListFragment.java
+++ b/mobile/android/base/home/RemoteTabsExpandableListFragment.java
@@ -230,17 +230,17 @@ public class RemoteTabsExpandableListFra
         // There is a delicate interaction, pre-KitKat, between
         // {add,remove}FooterView and setAdapter. setAdapter wraps the adapter
         // in a footer/header-managing adapter, which only happens (pre-KitKat)
         // if a footer/header is present. Therefore, we add our footer before
         // setting the adapter; and then we remove it afterward. From there on,
         // we can add/remove it at will.
         mList.addFooterView(mFooterView, null, true);
 
-        // Intialize adapter
+        // Initialize adapter
         mAdapter = new RemoteTabsExpandableListAdapter(R.layout.home_remote_tabs_group, R.layout.home_remote_tabs_child, null);
         mList.setAdapter(mAdapter);
 
         // Now the adapter is wrapped; we can remove our footer view.
         mList.removeFooterView(mFooterView);
 
         // Create callbacks before the initial loader is started
         mCursorLoaderCallbacks = new CursorLoaderCallbacks();
--- a/mobile/android/base/home/TwoLinePageRow.java
+++ b/mobile/android/base/home/TwoLinePageRow.java
@@ -246,17 +246,17 @@ public class TwoLinePageRow extends Line
         if (url.equals(mPageUrl)) {
             return;
         }
 
         // Blank the Favicon, so we don't show the wrong Favicon if we scroll and miss DB.
         mFavicon.clearImage();
         Favicons.cancelFaviconLoad(mLoadFaviconJobId);
 
-        // Displayed RecentTabsPanel urls may refer to pages openned in readermode, so we
+        // Displayed RecentTabsPanel URLs may refer to pages opened in reader mode, so we
         // remove the about:reader prefix to ensure the Favicon loads properly.
         final String pageURL = AboutPages.isAboutReader(url) ?
             ReaderModeUtils.getUrlFromAboutReader(url) : url;
         mLoadFaviconJobId = Favicons.getSizedFaviconForPageFromLocal(getContext(), pageURL, mFaviconListener);
 
         updateDisplayedUrl(url);
     }
 
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -537,17 +537,17 @@ just addresses the organization to follo
 <!-- Miscellaneous -->
 <!-- LOCALIZATION NOTE (ellipsis): This text is appended to a piece of text that does not fit in the
      designated space. Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit
      traditions in your locale. -->
 <!ENTITY ellipsis "…">
 
 <!ENTITY colon ":">
 
-<!-- These are only used for accessiblity for the done and overflow-menu buttons in the actionbar.
+<!-- These are only used for accessibility for the done and overflow-menu buttons in the actionbar.
      They are never shown to users -->
 <!ENTITY actionbar_menu "Menu">
 <!ENTITY actionbar_done "Done">
 
 <!-- Localization note (remote_tabs_last_synced): the variable is replaced by a
      "relative time span string" produced by Android.  This string describes the
      time the tabs were last synced relative to the current time; examples
      include "42 minutes ago", "4 days ago", "last week", etc. The subject of
--- a/mobile/android/base/overlays/service/OverlayActionService.java
+++ b/mobile/android/base/overlays/service/OverlayActionService.java
@@ -3,36 +3,32 @@
  * 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/. */
 
 package org.mozilla.gecko.overlays.service;
 
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Parcelable;
 import android.util.Log;
 import android.view.View;
 import org.mozilla.gecko.Assert;
-import org.mozilla.gecko.overlays.OverlayConstants;
 import org.mozilla.gecko.overlays.service.sharemethods.AddBookmark;
 import org.mozilla.gecko.overlays.service.sharemethods.AddToReadingList;
 import org.mozilla.gecko.overlays.service.sharemethods.SendTab;
 import org.mozilla.gecko.overlays.service.sharemethods.ShareMethod;
 import org.mozilla.gecko.overlays.ui.OverlayToastHelper;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.util.EnumMap;
 import java.util.Map;
 
 import static org.mozilla.gecko.overlays.OverlayConstants.ACTION_PREPARE_SHARE;
 import static org.mozilla.gecko.overlays.OverlayConstants.ACTION_SHARE;
-import static org.mozilla.gecko.overlays.OverlayConstants.EXTRA_SHARE_METHOD;
 
 /**
  * A service to receive requests from overlays to perform actions.
  * See OverlayConstants for details of the intent API supported by this service.
  *
  * Currently supported operations are:
  *
  * Add bookmark*
@@ -115,17 +111,17 @@ public class OverlayActionService extend
 
                 ShareMethod shareMethod = shareTypes.get(shareData.shareMethodType);
 
                 final ShareMethod.Result result = shareMethod.handle(shareData);
                 // Dispatch the share to the targeted ShareMethod.
                 switch (result) {
                     case SUCCESS:
                         // \o/
-                        OverlayToastHelper.showSuccessToast(getApplicationContext(), shareMethod.getSuccessMesssage());
+                        OverlayToastHelper.showSuccessToast(getApplicationContext(), shareMethod.getSuccessMessage());
                         break;
                     case TRANSIENT_FAILURE:
                         // An OnClickListener to do this share again.
                         View.OnClickListener retryListener = new View.OnClickListener() {
                             @Override
                             public void onClick(View view) {
                                 handleShare(intent);
                             }
--- a/mobile/android/base/overlays/service/sharemethods/AddBookmark.java
+++ b/mobile/android/base/overlays/service/sharemethods/AddBookmark.java
@@ -20,17 +20,17 @@ public class AddBookmark extends ShareMe
 
         LocalBrowserDB browserDB = new LocalBrowserDB(GeckoProfile.DEFAULT_PROFILE);
         browserDB.addBookmark(resolver, shareData.title, shareData.url);
 
         return Result.SUCCESS;
     }
 
     @Override
-    public String getSuccessMesssage() {
+    public String getSuccessMessage() {
         return context.getResources().getString(R.string.bookmark_added);
     }
 
     // Unused.
     @Override
     public String getFailureMessage() {
         return null;
     }
--- a/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java
+++ b/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java
@@ -35,17 +35,17 @@ public class AddToReadingList extends Sh
         values.put(Bookmarks.URL, shareData.url);
 
         browserDB.addReadingListItem(resolver, values);
 
         return Result.SUCCESS;
     }
 
     @Override
-    public String getSuccessMesssage() {
+    public String getSuccessMessage() {
         return context.getResources().getString(R.string.reading_list_added);
     }
 
     // Unused.
     @Override
     public String getFailureMessage() {
         return null;
     }
--- a/mobile/android/base/overlays/service/sharemethods/SendTab.java
+++ b/mobile/android/base/overlays/service/sharemethods/SendTab.java
@@ -53,17 +53,17 @@ public class SendTab extends ShareMethod
 
     // Key used in the extras Bundle in the share intent used for a send tab ShareMethod.
     public static final String SEND_TAB_TARGET_DEVICES = "SEND_TAB_TARGET_DEVICES";
 
     // Key used in broadcast intent from SendTab ShareMethod specifying available ClientRecords.
     public static final String EXTRA_CLIENT_RECORDS = "RECORDS";
 
     // The intent we should dispatch when the button for this ShareMethod is tapped, instead of
-    // taking the normal action (eg. "Set up sync!")
+    // taking the normal action (e.g., "Set up Sync!")
     public static final String OVERRIDE_INTENT = "OVERRIDE_INTENT";
 
     private Set<String> validGUIDs;
 
     // A TabSender appropriate to the account type we're connected to.
     private TabSender tabSender;
 
     @Override
@@ -284,17 +284,17 @@ public class SendTab extends ShareMethod
                 out.add(entry.getValue());
             }
         }
 
         return out;
     }
 
     @Override
-    public String getSuccessMesssage() {
+    public String getSuccessMessage() {
         return context.getResources().getString(R.string.sync_text_tab_sent);
     }
 
     @Override
     public String getFailureMessage() {
         return context.getResources().getString(R.string.sync_text_tab_not_sent);
     }
 
--- a/mobile/android/base/overlays/service/sharemethods/ShareMethod.java
+++ b/mobile/android/base/overlays/service/sharemethods/ShareMethod.java
@@ -28,17 +28,17 @@ public abstract class ShareMethod {
      * @param url The URL of the page to be shared. Never null.
      * @param extra A Parcelable of ShareMethod-specific parameters that may be provided by the
      *              caller. Generally null, but this field may be used to provide extra input to
      *              the ShareMethod (such as the device to share to in the case of SendTab).
      * @return true if the attempt to share was a success. False in the event of an error.
      */
     public abstract Result handle(ShareData shareData);
 
-    public abstract String getSuccessMesssage();
+    public abstract String getSuccessMessage();
     public abstract String getFailureMessage();
 
     /**
      * Enum representing the possible results of performing a share.
      */
     public static enum Result {
         // Victory!
         SUCCESS,
--- a/mobile/android/base/overlays/ui/OverlayDialogButton.java
+++ b/mobile/android/base/overlays/ui/OverlayDialogButton.java
@@ -37,17 +37,17 @@ public class OverlayDialogButton extends
     private String enabledLabel;
     private Drawable enabledIcon;
 
     // Label/icon used when disabled.
     private String disabledLabel;
     private Drawable disabledIcon;
 
     // Click listeners used when enabled/disabled. Currently, disabledOnClickListener is set
-    // intenally to something that causes the icon to pulse.
+    // internally to something that causes the icon to pulse.
     private OnClickListener enabledOnClickListener;
     private OnClickListener disabledOnClickListener;
 
     private boolean isEnabled = true;
 
     public OverlayDialogButton(Context context) {
         super(context);
         init(context);
--- a/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java
+++ b/mobile/android/base/overlays/ui/SendTabDeviceListArrayAdapter.java
@@ -1,30 +1,32 @@
 /* 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/. */
 
 package org.mozilla.gecko.overlays.ui;
 
-import android.app.AlertDialog;
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
+import java.util.Collection;
+
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.Assert;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.overlays.service.sharemethods.ParcelableClientRecord;
+import org.mozilla.gecko.overlays.ui.SendTabList.State;
 
-import java.util.Collection;
-
-import static org.mozilla.gecko.overlays.ui.SendTabList.*;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
 
 public class SendTabDeviceListArrayAdapter extends ArrayAdapter<ParcelableClientRecord> {
+    @SuppressWarnings("unused")
     private static final String LOGTAG = "GeckoSendTabAdapter";
 
     private State currentState;
 
     // String to display when in a "button-like" special state. Instead of using a
     // ParcelableClientRecord we override the rendering using this string.
     private String dummyRecordName;
 
--- a/mobile/android/base/overlays/ui/SendTabList.java
+++ b/mobile/android/base/overlays/ui/SendTabList.java
@@ -1,32 +1,32 @@
 /* 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/. */
 
 package org.mozilla.gecko.overlays.ui;
 
+import static org.mozilla.gecko.overlays.ui.SendTabList.State.LIST;
+import static org.mozilla.gecko.overlays.ui.SendTabList.State.LOADING;
+import static org.mozilla.gecko.overlays.ui.SendTabList.State.NONE;
+import static org.mozilla.gecko.overlays.ui.SendTabList.State.SHOW_DEVICES;
+
+import java.util.Arrays;
+
+import org.mozilla.gecko.Assert;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.overlays.service.sharemethods.ParcelableClientRecord;
+
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.widget.ListAdapter;
 import android.widget.ListView;
-import org.mozilla.gecko.Assert;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.overlays.service.sharemethods.ParcelableClientRecord;
-
-import java.util.Arrays;
-
-import static org.mozilla.gecko.overlays.ui.SendTabList.State.LIST;
-import static org.mozilla.gecko.overlays.ui.SendTabList.State.LOADING;
-import static org.mozilla.gecko.overlays.ui.SendTabList.State.NONE;
-import static org.mozilla.gecko.overlays.ui.SendTabList.State.SHOW_DEVICES;
 
 /**
  * The SendTab button has a few different states depending on the available devices (and whether
  * we've loaded them yet...)
  *
  * Initially, the view resembles a disabled button. (the LOADING state)
  * Once state is loaded from Sync's database, we know how many devices the user may send their tab
  * to.
@@ -39,17 +39,18 @@ import static org.mozilla.gecko.overlays
  * If the number of targets does not MAX_INLINE_SYNC_TARGETS, we present a button for each of them.
  * (the LIST state)
  *
  * Otherwise, we enter the SHOW_DEVICES state, in which we display a "Send to other devices" button
  * that takes the user to a menu for selecting a target device from their complete list of many
  * devices.
  */
 public class SendTabList extends ListView {
-    private static final String LOGTAG = "SendTabList";
+    @SuppressWarnings("unused")
+    private static final String LOGTAG = "GeckoSendTabList";
 
     // The maximum number of target devices to show in the main list. Further devices are available
     // from a secondary menu.
     public static final int MAXIMUM_INLINE_ELEMENTS = 2;
 
     private SendTabDeviceListArrayAdapter clientListAdapter;
 
     // Listener to fire when a share target is selected (either directly or via the prompt)
@@ -102,37 +103,35 @@ public class SendTabList extends ListVie
         }
 
         clientListAdapter.switchState(state);
         if (state == SHOW_DEVICES) {
             clientListAdapter.setDialog(getDialog());
         }
     }
 
-    public void setSyncClients(ParcelableClientRecord[] clients) {
-        if (clients == null) {
-            clients = new ParcelableClientRecord[0];
-        }
+    public void setSyncClients(final ParcelableClientRecord[] c) {
+        final ParcelableClientRecord[] clients = c == null ? new ParcelableClientRecord[0] : c;
 
         int size = clients.length;
         if (size == 0) {
-            // Just show a button to set up sync (or whatever).
+            // Just show a button to set up Sync (or whatever).
             switchState(NONE);
             return;
         }
 
         clientListAdapter.setClientRecordList(Arrays.asList(clients));
 
         if (size <= MAXIMUM_INLINE_ELEMENTS) {
-            // Show the list of devices inline.
+            // Show the list of devices in-line.
             switchState(LIST);
             return;
         }
 
-        // Just show a button to launch the list of devices to choose one from.
+        // Just show a button to launch the list of devices to choose from.
         switchState(SHOW_DEVICES);
     }
 
     /**
      * Get an AlertDialog listing all devices, allowing the user to select the one they want.
      * Used when more than MAXIMUM_INLINE_ELEMENTS devices are found (to avoid displaying them all
      * inline and looking crazy.
      */
--- a/mobile/android/base/prompts/IntentChooserPrompt.java
+++ b/mobile/android/base/prompts/IntentChooserPrompt.java
@@ -3,17 +3,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.prompts;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.widget.GeckoActionProvider;
 
-import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.widget.ListView;
 import android.util.Log;
 
@@ -112,17 +111,17 @@ public class IntentChooserPrompt {
     }
 
     // Gets a list of PromptListItems for a GeckoActionProvider
     private ArrayList<PromptListItem> getItems(final Context context, final GeckoActionProvider provider) {
         final ArrayList<PromptListItem> items = new ArrayList<PromptListItem>();
 
         // Add any intents from the provider.
         final PackageManager packageManager = context.getPackageManager();
-        final ArrayList<ResolveInfo> infos = provider.getSortedActivites();
+        final ArrayList<ResolveInfo> infos = provider.getSortedActivities();
 
         for (final ResolveInfo info : infos) {
             items.add(getItemForResolveInfo(info, packageManager, provider.getIntent()));
         }
 
         return items;
     }
 
--- a/mobile/android/base/prompts/Prompt.java
+++ b/mobile/android/base/prompts/Prompt.java
@@ -371,29 +371,29 @@ public class Prompt implements OnClickLi
 
         return linearLayout;
     }
 
     /* Add the requested input elements to the dialog.
      *
      * @param builder
      *        the alert builder currently building this dialog.
-     * @return 
+     * @return
      *         return true if the inputs were added successfully. This may fail
-     *         if the requested input is compatible with this Android verison
+     *         if the requested input is compatible with this Android version.
      */
     private boolean addInputs(AlertDialog.Builder builder) {
         int length = mInputs == null ? 0 : mInputs.length;
         if (length == 0) {
             return true;
         }
 
         try {
             View root = null;
-            boolean scrollable = false; // If any of the innuts are scrollable, we won't wrap this in a ScrollView
+            boolean scrollable = false; // If any of the inputs are scrollable, we won't wrap this in a ScrollView
 
             if (length == 1) {
                 root = wrapInput(mInputs[0]);
                 scrollable |= mInputs[0].getScrollable();
             } else if (length > 1) {
                 LinearLayout linearLayout = new LinearLayout(mContext);
                 linearLayout.setOrientation(LinearLayout.VERTICAL);
                 for (int i = 0; i < length; i++) {
--- a/mobile/android/base/sync/config/ConfigurationMigrator.java
+++ b/mobile/android/base/sync/config/ConfigurationMigrator.java
@@ -366,17 +366,17 @@ public class ConfigurationMigrator {
     }
 
     // Now we're down to either version 0 or version 1.
     if (currentVersion == 0 && desiredVersion == 1) {
       Logger.info(LOG_TAG, "Upgrading from version 0 to version 1.");
       upgrade0to1(context, accountManager, account, product, username, serverURL, profile);
     } else if (currentVersion == 1 && desiredVersion == 0) {
       Logger.info(LOG_TAG, "Upgrading from version 0 to version 1.");
-      upgrade0to1(context, accountManager, account, product, username, serverURL, profile);
+      downgrade1to0(context, accountManager, account, product, username, serverURL, profile);
     } else {
       Logger.warn(LOG_TAG, "Don't know how to migrate from version " + currentVersion + " to " + desiredVersion + ".");
     }
 
     Logger.info(LOG_TAG, "Migrated from version " + currentVersion + " to version " + desiredVersion + ".");
     versionPrefs.edit().putLong(SyncConfiguration.PREF_PREFS_VERSION, desiredVersion).commit();
   }
 }
--- a/mobile/android/base/tabs/TabsLayoutItemView.java
+++ b/mobile/android/base/tabs/TabsLayoutItemView.java
@@ -109,12 +109,12 @@ public class TabsLayoutItemView extends 
     public int getTabId() {
         return mTabId;
     }
 
     public void setThumbnail(Drawable thumbnail) {
         mThumbnail.setImageDrawable(thumbnail);
     }
 
-    public void setCloseVisibile(boolean visible) {
+    public void setCloseVisible(boolean visible) {
         mCloseButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
     }
 }
--- a/mobile/android/base/tabs/TabsListLayout.java
+++ b/mobile/android/base/tabs/TabsListLayout.java
@@ -76,17 +76,17 @@ class TabsListLayout extends TwoWayView
         setOnTouchListener(mSwipeListener);
         setOnScrollListener(mSwipeListener.makeScrollListener());
 
         setRecyclerListener(new RecyclerListener() {
             @Override
             public void onMovedToScrapHeap(View view) {
                 TabsLayoutItemView item = (TabsLayoutItemView) view;
                 item.setThumbnail(null);
-                item.setCloseVisibile(true);
+                item.setCloseVisible(true);
             }
         });
     }
 
     private class TabsListLayoutAdapter extends TabsLayoutAdapter {
         private final Button.OnClickListener mCloseOnClickListener;
         public TabsListLayoutAdapter (Context context) {
             super(context);
@@ -392,17 +392,17 @@ class TabsListLayout extends TwoWayView
 
 
         animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() {
             @Override
             public void onPropertyAnimationStart() { }
             @Override
             public void onPropertyAnimationEnd() {
                 TabsLayoutItemView tab = (TabsLayoutItemView) view;
-                tab.setCloseVisibile(true);
+                tab.setCloseVisible(true);
             }
         });
 
         animator.start();
     }
 
     private class TabSwipeGestureListener implements View.OnTouchListener {
         // same value the stock browser uses for after drag animation velocity in pixels/sec
@@ -577,17 +577,17 @@ class TabsListLayout extends TwoWayView
                     // set pressed state on the swiped view.
                     if (isScrollingX || isScrollingY)
                         cancelCheckForTap();
 
                     if (isSwipingToClose) {
                         mSwiping = true;
                         TabsListLayout.this.requestDisallowInterceptTouchEvent(true);
 
-                        ((TabsLayoutItemView) mSwipeView).setCloseVisibile(false);
+                        ((TabsLayoutItemView) mSwipeView).setCloseVisible(false);
 
                         // Stops listview from highlighting the touched item
                         // in the list when swiping.
                         MotionEvent cancelEvent = MotionEvent.obtain(e);
                         cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
                                 (e.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                         TabsListLayout.this.onTouchEvent(cancelEvent);
                         cancelEvent.recycle();
--- a/mobile/android/base/tests/ContentContextMenuTest.java
+++ b/mobile/android/base/tests/ContentContextMenuTest.java
@@ -12,17 +12,17 @@ import android.util.DisplayMetrics;
 abstract class ContentContextMenuTest extends PixelTest {
     private static final int MAX_TEST_TIMEOUT = 10000;
 
     // This method opens the context menu of any web content. It assumes that the page is already loaded
     protected void openWebContentContextMenu(String waitText) {
         DisplayMetrics dm = new DisplayMetrics();
         getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
 
-        // The web content we are trying to open the context menu for should be positioned at the top of the page, at least 60px heigh and aligned to the middle
+        // The web content we are trying to open the context menu for should be positioned at the top of the page, at least 60px high and aligned to the middle
         float top = mDriver.getGeckoTop() + 30 * dm.density;
         float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2;
 
         mAsserter.dumpLog("long-clicking at "+left+", "+top);
         mSolo.clickLongOnScreen(left, top);
         waitForText(waitText);
     }
 
--- a/mobile/android/base/tests/components/GeckoViewComponent.java
+++ b/mobile/android/base/tests/components/GeckoViewComponent.java
@@ -88,17 +88,17 @@ public class GeckoViewComponent extends 
                 public boolean isSatisfied() {
                     return isActive();
                 }
             });
             return this;
         }
 
         /**
-         * Returns whether an InputConnection is avaiable.
+         * Returns whether an InputConnection is available.
          * An InputConnection is available when text input is being directed to the
          * GeckoView, and a text field (input, textarea, contentEditable, etc.) is
          * currently focused inside the GeckoView.
          */
         private boolean hasInputConnection() {
             final InputMethodManager imm = getInputMethodManager();
             return imm.isActive(getView()) && imm.isAcceptingText();
         }
--- a/mobile/android/base/tests/helpers/AssertionHelper.java
+++ b/mobile/android/base/tests/helpers/AssertionHelper.java
@@ -13,17 +13,17 @@ import org.mozilla.gecko.tests.UITestCon
  * Provides assertions in a JUnit-like API that wraps the robocop Assert interface.
  */
 public final class AssertionHelper {
     // Assert.ok has a "diag" ("diagnostic") parameter that has no useful purpose.
     private static final String DIAG_STRING = "";
 
     private static Assert sAsserter;
 
-    private AssertionHelper() { /* To disallow instantation. */ }
+    private AssertionHelper() { /* To disallow instantiation. */ }
 
     protected static void init(final UITestContext context) {
         sAsserter = context.getAsserter();
     }
 
     public static void fAssertArrayEquals(final String message, final byte[] expecteds, final byte[] actuals) {
         sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING);
     }
--- a/mobile/android/base/tests/testBrowserProvider.java
+++ b/mobile/android/base/tests/testBrowserProvider.java
@@ -327,17 +327,17 @@ public class testBrowserProvider extends
             }
 
             boolean seenException = false;
             try {
                 applyResult = mProvider.applyBatch(mOperations);
             } catch (OperationApplicationException ex) {
                 seenException = true;
             }
-            mAsserter.is(seenException, false, "Batch updating succeded");
+            mAsserter.is(seenException, false, "Batch updating succeeded");
             mOperations.clear();
 
             // Delete all visits
             for (int i = 0; i < TESTCOUNT; i++) {
                 builder = ContentProviderOperation.newDelete(BrowserContract.History.CONTENT_URI);
                 builder.withSelection(BrowserContract.History.URL  + " = ?",
                                       new String[] {"http://www.test.org/" + i});
                 builder.withExpectedCount(1);
--- a/mobile/android/base/tests/testFilterOpenTab.java
+++ b/mobile/android/base/tests/testFilterOpenTab.java
@@ -11,17 +11,17 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.TabsProvider;
 
 import android.content.ContentProvider;
 import android.content.Context;
 import android.database.Cursor;
 
 /**
  * Tests that local tabs are filtered prior to upload.
- * - create a set of tabs and perists them through TabsAccessor.
+ * - create a set of tabs and persists them through TabsAccessor.
  * - verifies that tabs are filtered by querying.
  */
 public class testFilterOpenTab extends ContentProviderTest {
     private static final String[] TABS_PROJECTION_COLUMNS = new String[] {
                                                                 BrowserContract.Tabs.TITLE,
                                                                 BrowserContract.Tabs.URL,
                                                                 BrowserContract.Clients.GUID,
                                                                 BrowserContract.Clients.NAME
--- a/mobile/android/base/tests/testHistory.java
+++ b/mobile/android/base/tests/testHistory.java
@@ -56,13 +56,13 @@ public class testHistory extends AboutHo
                 return true;
             }
         }, MAX_WAIT_MS);
 
         mAsserter.isnot(mFirstChild, null, "Got history item");
         mSolo.clickOnView(mFirstChild);
 
         // The first item here (since it was just visited) should be a "Switch to tab" item
-        // i.e. don't expect a DOMCOntentLoaded event
+        // i.e. don't expect a DOMContentLoaded event
         verifyPageTitle(StringHelper.ROBOCOP_BLANK_PAGE_03_URL);
         verifyUrl(url3);
     }
 }
--- a/mobile/android/base/tests/testShareLink.java
+++ b/mobile/android/base/tests/testShareLink.java
@@ -42,17 +42,17 @@ public class testShareLink extends About
         selectMenuItem(StringHelper.SHARE_LABEL);
         if (Build.VERSION.SDK_INT >= 14) {
             // Check for our own sync in the submenu.
             waitForText("Sync$");
         } else {
             waitForText("Share via");
         }
 
-        // Get list of current avaliable share activities and verify them
+        // Get list of current available share activities and verify them
         shareOptions = getShareOptions();
         ArrayList<String> displayedOptions = getShareOptionsList();
         for (String option:shareOptions) {
              // Verify if the option is present in the list of displayed share options
              mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option found", option);
         }
 
         // Test share from the urlbar context menu
@@ -144,17 +144,17 @@ public class testShareLink extends About
         for (String option:shareOptions) {
              // Verify if the option is present in the list of displayed share options
              mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option for " + openedFrom + (openedFrom.equals("urlbar") ? "" : " item") + " found", option);
         }
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
         /**
          * Adding a wait for the page title to make sure the Awesomebar will be dismissed
          * Because of Bug 712370 the Awesomescreen will be dismissed when the Share Menu is closed
-         * so there is no need for handeling this different depending on where the share menu was invoced from
+         * so there is no need for handling this different depending on where the share menu was invoked from
          * TODO: Look more into why the delay is needed here now and it was working before
          */
         waitForText(urlTitle);
     }
 
     // Create a SEND intent and get the possible activities offered
     public ArrayList<String> getShareOptions() {
         ArrayList<String> shareOptions = new ArrayList<>();
--- a/mobile/android/base/tests/testTitleBar.java
+++ b/mobile/android/base/tests/testTitleBar.java
@@ -15,22 +15,22 @@ public class testTitleBar extends PixelT
 
         String blank1 = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         String title = StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE;
 
         // Loading a page
         inputAndLoadUrl(blank1);
         verifyPageTitle(title);
 
-        // Verifing the full URL is displayed in the URL Bar
+        // Ensure the full URL is displayed in the URL Bar
         selectOption(StringHelper.SHOW_PAGE_ADDRESS_LABEL);
         inputAndLoadUrl(blank1);
         verifyUrl(blank1);
 
-        // Verifing the title is displayed in the URL Bar
+        // Ensure the title is displayed in the URL Bar
         selectOption(StringHelper.SHOW_PAGE_TITLE_LABEL);
         inputAndLoadUrl(blank1);
         verifyPageTitle(title);
     }
 
     // Entering settings, changing the options: show title/page address option and verifing the device type because for phone there is an extra back action to exit the settings menu
     public void selectOption(String option) {
         selectSettingsItem(StringHelper.DISPLAY_SECTION_LABEL, StringHelper.TITLE_BAR_LABEL);
--- a/mobile/android/base/tests/testVkbOverlap.java
+++ b/mobile/android/base/tests/testVkbOverlap.java
@@ -65,17 +65,17 @@ public class testVkbOverlap extends Pixe
         paintExpecter.unregisterListener();
         painted = mDriver.getPaintedSurface();
         try {
             // if the vkb scrolled into view as expected, then the number of green pixels now visible should be about the
             // same as it was before, since the green pixels indicate the text input is in view. use a fudge factor of 0.9 to
             // account for borders and such of the text input which might still be out of view.
             int newCount = countGreenPixels(painted);
 
-            // if zooming is allowed, the number of green pixels visible should have increased substatially
+            // if zooming is allowed, the number of green pixels visible should have increased substantially
             if (shouldZoom) {
                 mAsserter.ok(newCount > greenPixelCount * 1.5, "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount);
             } else {
                 mAsserter.ok((Math.abs(greenPixelCount - newCount) / greenPixelCount < 0.1), "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount);
             }
         } finally {
             painted.close();
         }
--- a/mobile/android/base/toolbar/CanvasDelegate.java
+++ b/mobile/android/base/toolbar/CanvasDelegate.java
@@ -16,17 +16,17 @@ import android.graphics.Shader;
 
 class CanvasDelegate {
     Paint mPaint;
     PorterDuffXfermode mMode;
     DrawManager mDrawManager;
 
     // DrawManager would do a default draw of the background.
     static interface DrawManager {
-        public void defaultDraw(Canvas cavas);
+        public void defaultDraw(Canvas canvas);
     }
 
     CanvasDelegate(DrawManager drawManager, Mode mode) {
         mDrawManager = drawManager;
 
         // DST_IN masks, DST_OUT clips.
         mMode = new PorterDuffXfermode(mode);
 
--- a/mobile/android/base/toolbar/SiteIdentityPopup.java
+++ b/mobile/android/base/toolbar/SiteIdentityPopup.java
@@ -97,17 +97,17 @@ public class SiteIdentityPopup extends A
             mVerifier.setText(verifier + "\n" + encrypted);
 
             mContent.setPadding(0, 0, 0, 0);
             mIdentity.setVisibility(View.VISIBLE);
         }
     }
 
     private void addMixedContentNotification(boolean blocked) {
-        // Remove any exixting mixed content notification.
+        // Remove any existing mixed content notification.
         removeMixedContentNotification();
         mMixedContentNotification = new DoorHanger(mContext, DoorHanger.Theme.DARK);
 
         String message;
         if (blocked) {
             message = mContext.getString(R.string.blocked_mixed_content_message_top) + "\n\n" +
                       mContext.getString(R.string.blocked_mixed_content_message_bottom);
         } else {
--- a/mobile/android/base/toolbar/ToolbarDisplayLayout.java
+++ b/mobile/android/base/toolbar/ToolbarDisplayLayout.java
@@ -575,17 +575,17 @@ public class ToolbarDisplayLayout extend
     void prepareStartEditingAnimation() {
         // Hide page actions/stop buttons immediately
         ViewHelper.setAlpha(mPageActionLayout, 0);
         ViewHelper.setAlpha(mStop, 0);
     }
 
     void prepareStopEditingAnimation(PropertyAnimator anim) {
         // Fade toolbar buttons (page actions, stop) after the entry
-        // is schrunk back to its original size.
+        // is shrunk back to its original size.
         anim.attach(mPageActionLayout,
                     PropertyAnimator.Property.ALPHA,
                     1);
 
         anim.attach(mStop,
                     PropertyAnimator.Property.ALPHA,
                     1);
     }
--- a/mobile/android/base/updater/UpdateService.java
+++ b/mobile/android/base/updater/UpdateService.java
@@ -217,17 +217,18 @@ public class UpdateService extends Inten
         int autoDownloadPolicy = getAutoDownloadPolicy();
 
 
         /**
          * We only start a download automatically if one of following criteria are met:
          *
          * - We have a FORCE_DOWNLOAD flag passed in
          * - The preference is set to 'always'
-         * - The preference is set to 'wifi' and we are using a non-metered network (i.e. the user is OK with large data transfers occuring)
+         * - The preference is set to 'wifi' and we are using a non-metered network (i.e. the user
+         *   is OK with large data transfers occurring)
          */
         boolean shouldStartDownload = hasFlag(flags, UpdateServiceHelper.FLAG_FORCE_DOWNLOAD) ||
             autoDownloadPolicy == UpdateServiceHelper.AUTODOWNLOAD_ENABLED ||
             (autoDownloadPolicy == UpdateServiceHelper.AUTODOWNLOAD_WIFI && !ConnectivityManagerCompat.isActiveNetworkMetered(mConnectivityManager));
 
         if (!shouldStartDownload) {
             Log.i(LOGTAG, "not initiating automatic update download due to policy " + autoDownloadPolicy);
             sendCheckUpdateResult(UpdateServiceHelper.CheckUpdateResult.AVAILABLE);
--- a/mobile/android/base/util/GeckoRequest.java
+++ b/mobile/android/base/util/GeckoRequest.java
@@ -18,17 +18,17 @@ public abstract class GeckoRequest {
     private final String data;
 
     /**
      * Creates a request that can be dispatched using
      * {@link GeckoAppShell#sendRequestToGecko(GeckoRequest)}.
      *
      * @param name The name of the event associated with this request, which must have a
      *             Gecko-side listener registered to respond to this request.
-     * @param data Data to send with this request, which can be any object serializeable by
+     * @param data Data to send with this request, which can be any object serializable by
      *             {@link JSONObject#put(String, Object)}.
      */
     @RobocopTarget
     public GeckoRequest(String name, Object data) {
         this.name = name;
         final JSONObject message = new JSONObject();
         try {
             message.put("id", id);
--- a/mobile/android/base/util/WebActivityMapper.java
+++ b/mobile/android/base/util/WebActivityMapper.java
@@ -49,17 +49,17 @@ public final class WebActivityMapper {
          * If 'type' is present in data object, uses the value as the MIME type.
          */
         @Override
         public String getMime(JSONObject data) throws JSONException {
             return data.optString("type", null);
         }
 
         /**
-         * If 'uri' or 'url' is present in data object, uses the respecitve value as the Uri.
+         * If 'uri' or 'url' is present in data object, uses the respective value as the Uri.
          */
         @Override
         public String getUri(JSONObject data) throws JSONException {
             // Will return uri or url if present.
             String uri = data.optString("uri", null);
             return uri != null ? uri : data.optString("url", null);
         }
     }
--- a/mobile/android/base/webapp/UninstallListener.java
+++ b/mobile/android/base/webapp/UninstallListener.java
@@ -141,13 +141,13 @@ public class UninstallListener extends B
         public DelayedStartupTask(GeckoApp app) {
             mApp = app;
         }
 
         @Override
         public void run() {
             ThreadUtils.assertOnBackgroundThread();
 
-            // Perform webapp uninstalls as appropiate.
+            // Perform webapp uninstalls as appropriate.
             UninstallListener.initUninstallPackageScan(mApp.getApplicationContext());
         }
     }
 }
--- a/mobile/android/base/widget/ActivityChooserModel.java
+++ b/mobile/android/base/widget/ActivityChooserModel.java
@@ -196,22 +196,16 @@ public class ActivityChooserModel extend
     private static final String ATTRIBUTE_TIME = "time";
 
     /**
      * Attribute for the choice weight.
      */
     private static final String ATTRIBUTE_WEIGHT = "weight";
 
     /**
-     * The default name of the choice history file.
-     */
-    public static final String DEFAULT_HISTORY_FILE_NAME =
-        "activity_choser_model_history.xml";
-
-    /**
      * The default maximal length of the choice history.
      */
     public static final int DEFAULT_HISTORY_MAX_LENGTH = 50;
 
     /**
      * The amount with which to inflate a chosen activity when set as default.
      */
     private static final int DEFAULT_ACTIVITY_INFLATION = 5;
@@ -322,29 +316,23 @@ public class ActivityChooserModel extend
     /**
      * Flag whether to reload the activities for the current intent.
      */
     boolean mReloadActivities;
 
     /**
      * Policy for controlling how the model handles chosen activities.
      */
-    private OnChooseActivityListener mActivityChoserModelPolicy;
+    private OnChooseActivityListener mActivityChooserModelPolicy;
 
     /**
      * Gets the data model backed by the contents of the provided file with historical data.
      * Note that only one data model is backed by a given file, thus multiple calls with
      * the same file name will return the same model instance. If no such instance is present
      * it is created.
-     * <p>
-     * <strong>Note:</strong> To use the default historical data file clients should explicitly
-     * pass as file name {@link #DEFAULT_HISTORY_FILE_NAME}. If no persistence of the choice
-     * history is desired clients should pass <code>null</code> for the file name. In such
-     * case a new model is returned for each invocation.
-     * </p>
      *
      * <p>
      * <strong>Always use difference historical data files for semantically different actions.
      * For example, sharing is different from importing.</strong>
      * </p>
      *
      * @param context Context for loading resources.
      * @param historyFileName File name with choice history, <code>null</code>
@@ -497,20 +485,20 @@ public class ActivityChooserModel extend
 
             ComponentName chosenName = new ComponentName(
                     chosenActivity.resolveInfo.activityInfo.packageName,
                     chosenActivity.resolveInfo.activityInfo.name);
 
             Intent choiceIntent = new Intent(mIntent);
             choiceIntent.setComponent(chosenName);
 
-            if (mActivityChoserModelPolicy != null) {
+            if (mActivityChooserModelPolicy != null) {
                 // Do not allow the policy to change the intent.
                 Intent choiceIntentCopy = new Intent(choiceIntent);
-                final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this,
+                final boolean handled = mActivityChooserModelPolicy.onChooseActivity(this,
                         choiceIntentCopy);
                 if (handled) {
                     return null;
                 }
             }
 
             HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
                     System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
@@ -522,17 +510,17 @@ public class ActivityChooserModel extend
 
     /**
      * Sets the listener for choosing an activity.
      *
      * @param listener The listener.
      */
     public void setOnChooseActivityListener(OnChooseActivityListener listener) {
         synchronized (mInstanceLock) {
-            mActivityChoserModelPolicy = listener;
+            mActivityChooserModelPolicy = listener;
         }
     }
 
     /**
      * Gets the default activity, The default activity is defined as the one
      * with highest rank i.e. the first one in the list of activities that can
      * handle the intent.
      *
--- a/mobile/android/base/widget/CheckableLinearLayout.java
+++ b/mobile/android/base/widget/CheckableLinearLayout.java
@@ -18,29 +18,31 @@ public class CheckableLinearLayout exten
     private CheckBox mCheckBox;
 
     public CheckableLinearLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     @Override
     public boolean isChecked() {
-        return mCheckBox != null ? mCheckBox.isChecked() : false;
+        return mCheckBox != null && mCheckBox.isChecked();
     }
 
     @Override
     public void setChecked(boolean isChecked) {
-        if (mCheckBox != null)
+        if (mCheckBox != null) {
             mCheckBox.setChecked(isChecked);
+        }
     }
 
     @Override
     public void toggle() {
-        if (mCheckBox != null)
+        if (mCheckBox != null) {
             mCheckBox.toggle();
+        }
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
 
         mCheckBox = (CheckBox) findViewById(R.id.checkbox);
         mCheckBox.setClickable(false);
--- a/mobile/android/base/widget/GeckoActionProvider.java
+++ b/mobile/android/base/widget/GeckoActionProvider.java
@@ -155,17 +155,17 @@ public class GeckoActionProvider {
             mOnTargetListener.onTargetSelected();
         }
     }
 
     public void setOnTargetSelectedListener(OnTargetSelectedListener listener) {
         mOnTargetListener = listener;
     }
 
-    public ArrayList<ResolveInfo> getSortedActivites() {
+    public ArrayList<ResolveInfo> getSortedActivities() {
         ArrayList<ResolveInfo> infos = new ArrayList<ResolveInfo>();
 
         ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
 
         // Populate the sub-menu with a sub set of the activities.
         final int count = dataModel.getActivityCount();
         for (int i = 0; i < count; i++) {
             infos.add(dataModel.getActivity(i));
--- a/mobile/android/base/widget/GeckoSwipeRefreshLayout.java
+++ b/mobile/android/base/widget/GeckoSwipeRefreshLayout.java
@@ -38,17 +38,17 @@ import android.view.animation.Animation.
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.Transformation;
 import android.widget.AbsListView;
 
 /**
  * GeckoSwipeRefreshLayout is mostly lifted from Android's support library (v4) with these
- * modfications:
+ * modifications:
  *  - Removes elastic "rubber banding" effect when overscrolling the child view.
  *  - Changes the height of the progress bar to match the height of HomePager's page indicator.
  *  - Uses a rectangle rather than a circle for the SwipeProgressBar indicator.
  *
  * This class also embeds package-access dependent classes SwipeProgressBar and
  * BakedBezierInterpolator.
  *
  * Original source: https://android.googlesource.com/platform/frameworks/support/+/
--- a/mobile/android/base/widget/TwoWayView.java
+++ b/mobile/android/base/widget/TwoWayView.java
@@ -6187,29 +6187,29 @@ public class TwoWayView extends AdapterV
                 }
             } else {
                 fireOnSelected();
                 performAccessibilityActionsOnSelected();
             }
         }
     }
 
-    private class WindowRunnnable {
+    private class WindowRunnable {
         private int mOriginalAttachCount;
 
         public void rememberWindowAttachCount() {
             mOriginalAttachCount = getWindowAttachCount();
         }
 
         public boolean sameWindow() {
             return hasWindowFocus() && getWindowAttachCount() == mOriginalAttachCount;
         }
     }
 
-    private class PerformClick extends WindowRunnnable implements Runnable {
+    private class PerformClick extends WindowRunnable implements Runnable {
         int mClickMotionPosition;
 
         @Override
         public void run() {
             if (mDataChanged) {
                 return;
             }
 
@@ -6274,17 +6274,17 @@ public class TwoWayView extends AdapterV
                     }
                 } else {
                     mTouchMode = TOUCH_MODE_DONE_WAITING;
                 }
             }
         }
     }
 
-    private class CheckForLongPress extends WindowRunnnable implements Runnable {
+    private class CheckForLongPress extends WindowRunnable implements Runnable {
         @Override
         public void run() {
             final int motionPosition = mMotionPosition;
             final View child = getChildAt(motionPosition - mFirstPosition);
 
             if (child != null) {
                 final long longPressId = mAdapter.getItemId(mMotionPosition);
 
@@ -6299,17 +6299,17 @@ public class TwoWayView extends AdapterV
                     child.setPressed(false);
                 } else {
                     mTouchMode = TOUCH_MODE_DONE_WAITING;
                 }
             }
         }
     }
 
-    private class CheckForKeyLongPress extends WindowRunnnable implements Runnable {
+    private class CheckForKeyLongPress extends WindowRunnable implements Runnable {
         @Override
         public void run() {
             if (!isPressed() || mSelectedPosition < 0) {
                 return;
             }
 
             final int index = mSelectedPosition - mFirstPosition;
             final View v = getChildAt(index);
--- a/mobile/android/chrome/content/FindHelper.js
+++ b/mobile/android/chrome/content/FindHelper.js
@@ -73,13 +73,13 @@ var FindHelper = {
           Cu.reportError("Warning: selected tab changed during find!");
           // fall through and restore viewport on the initial tab anyway
         }
         this._targetTab.setViewport(JSON.parse(this._initialViewport));
         this._targetTab.sendViewportUpdate();
       }
     } else {
       // Disabled until bug 1014113 is fixed
-      //ZoomHelper.zoomToRect(aData.rect, -1, false, true);
+      // ZoomHelper.zoomToRect(aData.rect);
       this._viewportChanged = true;
     }
   }
 };
--- a/mobile/android/chrome/content/ZoomHelper.js
+++ b/mobile/android/chrome/content/ZoomHelper.js
@@ -76,72 +76,76 @@ var ZoomHelper = {
             dw > minDifference && dw < maxDifference);
   },
 
   /* Zoom to an element, optionally keeping a particular part of it
    * in view if it is really tall.
    */
   zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) {
     let rect = ElementTouchHelper.getBoundingContentRect(aElement);
-    ZoomHelper.zoomToRect(rect, aClickY, aCanZoomOut, aCanScrollHorizontally, aElement);
-  },
 
-  zoomToRect: function(aRect, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true, aElement) {
     const margin = 15;
 
-    if(!aRect.h || !aRect.w) {
-      aRect.h = aRect.height;
-      aRect.w = aRect.width;
-    }
 
     let viewport = BrowserApp.selectedTab.getViewport();
-    let bRect = new Rect(aCanScrollHorizontally ? Math.max(viewport.cssPageLeft, aRect.x - margin) : viewport.cssX,
-                         aRect.y,
-                         aCanScrollHorizontally ? aRect.w + 2 * margin : viewport.cssWidth,
-                         aRect.h);
+    rect = new Rect(aCanScrollHorizontally ? Math.max(viewport.cssPageLeft, rect.x - margin) : viewport.cssX,
+                    rect.y,
+                    aCanScrollHorizontally ? rect.w + 2 * margin : viewport.cssWidth,
+                    rect.h);
     // constrict the rect to the screen's right edge
-    bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x);
+    rect.width = Math.min(rect.width, viewport.cssPageRight - rect.x);
 
     // if the rect is already taking up most of the visible area and is stretching the
     // width of the page, then we want to zoom out instead.
     if (aElement) {
       if (BrowserEventHandler.mReflozPref) {
         let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement);
 
-        bRect.width = zoomFactor <= 1.0 ? bRect.width : gScreenWidth / zoomFactor;
-        bRect.height = zoomFactor <= 1.0 ? bRect.height : bRect.height / zoomFactor;
-        if (zoomFactor == 1.0 || ZoomHelper.isRectZoomedIn(bRect, viewport)) {
+        rect.width = zoomFactor <= 1.0 ? rect.width : gScreenWidth / zoomFactor;
+        rect.height = zoomFactor <= 1.0 ? rect.height : rect.height / zoomFactor;
+        if (zoomFactor == 1.0 || ZoomHelper.isRectZoomedIn(rect, viewport)) {
           if (aCanZoomOut) {
             ZoomHelper.zoomOut();
           }
           return;
         }
-      } else if (ZoomHelper.isRectZoomedIn(bRect, viewport)) {
+      } else if (ZoomHelper.isRectZoomedIn(rect, viewport)) {
         if (aCanZoomOut) {
           ZoomHelper.zoomOut();
         }
         return;
       }
+
+      ZoomHelper.zoomToRect(rect, aClickY);
     }
+  },
 
-    let rect = {};
+  /* Zoom to a specific part of the screen defined by a rect,
+   * optionally keeping a particular part of it in view
+   * if it is really tall.
+   */
+  zoomToRect: function(aRect, aClickY = -1) {
+    let viewport = BrowserApp.selectedTab.getViewport();
+
+    let rect = {
+      x: aRect.x,
+      y: aRect.y,
+      w: aRect.width,
+      h: Math.min(aRect.width * viewport.cssHeight / viewport.cssWidth, aRect.height)
+    };
 
     rect.type = "Browser:ZoomToRect";
-    rect.x = bRect.x;
-    rect.y = bRect.y;
-    rect.w = bRect.width;
-    rect.h = Math.min(bRect.width * viewport.cssHeight / viewport.cssWidth, bRect.height);
 
     if (aClickY >= 0) {
       // if the block we're zooming to is really tall, and we want to keep a particular
       // part of it in view, then adjust the y-coordinate of the target rect accordingly.
-      // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal
+      // the 1.2 multiplier is just a little fuzz to compensate for aRect including horizontal 
       // margins but not vertical ones.
       let cssTapY = viewport.cssY + aClickY;
-      if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
+      if ((aRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
         rect.y = cssTapY - (rect.h / 2);
       }
     }
 
     if (rect.w > viewport.cssWidth || rect.h > viewport.cssHeight) {
       BrowserEventHandler.resetMaxLineBoxWidth();
     }
 
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -290,17 +290,17 @@ AboutReader.prototype = {
   _scrollPage: function Reader_scrollPage(scrollByPixels) {
     let viewport = BrowserApp.selectedTab.getViewport();
     let newY = Math.min(Math.max(viewport.cssY + scrollByPixels, viewport.cssPageTop), viewport.cssPageBottom);
     let newRect = new Rect(viewport.cssX, newY, viewport.cssWidth, viewport.cssHeight);
 
     this._setToolbarVisibility(false);
     this._setBrowserToolbarVisiblity(false);
     this._scrolled  = true;
-    ZoomHelper.zoomToRect(newRect, -1, false, false);
+    ZoomHelper.zoomToRect(newRect, -1);
   },
 
   _updateToggleButton: function Reader_updateToggleButton() {
     let classes = this._doc.getElementById("toggle-button").classList;
 
     if (this._isReadingListItem == 1) {
       classes.add("on");
     } else {
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java
+++ b/mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java
@@ -34,17 +34,17 @@ import android.widget.TextView;
 
 public class SearchBar extends FrameLayout {
 
     private final EditText editText;
     private final ImageButton clearButton;
     private final ImageView engineIcon;
 
     private final Drawable focusedBackground;
-    private final Drawable defaultBackgound;
+    private final Drawable defaultBackground;
 
     private final InputMethodManager inputMethodManager;
 
     private TextListener listener;
 
     private boolean active;
 
     public interface TextListener {
@@ -106,17 +106,17 @@ public class SearchBar extends FrameLayo
             @Override
             public void onClick(View v) {
                 editText.setText("");
             }
         });
         engineIcon = (ImageView) findViewById(R.id.engine_icon);
 
         focusedBackground = getResources().getDrawable(R.drawable.edit_text_focused);
-        defaultBackgound = getResources().getDrawable(R.drawable.edit_text_default);
+        defaultBackground = getResources().getDrawable(R.drawable.edit_text_default);
 
         inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     }
 
     public void setText(String text) {
         editText.setText(text);
 
         // Move cursor to end of search input.
@@ -161,17 +161,17 @@ public class SearchBar extends FrameLayo
         editText.setFocusableInTouchMode(active);
 
         final int leftDrawable = active ? R.drawable.search_icon_active : R.drawable.search_icon_inactive;
         editText.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, 0, 0, 0);
 
         // We can't use a selector drawable because we apply a color filter to the focused
         // background at run time.
         // TODO: setBackgroundDrawable is deprecated in API level 16
-        editText.setBackgroundDrawable(active ? focusedBackground : defaultBackgound);
+        editText.setBackgroundDrawable(active ? focusedBackground : defaultBackground);
 
         if (active) {
             editText.requestFocus();
             inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
         } else {
             editText.clearFocus();
             inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
         }
--- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java
+++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/scanners/ScanManager.java
@@ -180,11 +180,11 @@ public class ScanManager {
 
     public void checkPrefs() {
         if (mGPSScanner != null) {
             mGPSScanner.checkPrefs();
         }
     }
 
     public boolean isGeofenced() {
-        return (mGPSScanner == null)? false : mGPSScanner.isGeofenced();
+        return (mGPSScanner != null) && mGPSScanner.isGeofenced();
     }
 }
--- a/mobile/android/themes/core/content.css
+++ b/mobile/android/themes/core/content.css
@@ -173,18 +173,16 @@ input[type="submit"],
 input[type="reset"],
 button {
   border-width: 1px;
   padding: 0 7px 0 7px;
 }
 
 input[type="radio"],
 input[type="checkbox"] {
-  max-width: 14px;
-  max-height: 14px;
   border: 1px solid @form_border@ !important;
   padding: 2px 1px 2px 1px;
 }
 
 select > button {
   border-width: 0px !important;
   margin: 0px !important;
   padding: 0px !important;
--- a/services/fxaccounts/tests/xpcshell/xpcshell.ini
+++ b/services/fxaccounts/tests/xpcshell/xpcshell.ini
@@ -1,16 +1,16 @@
 [DEFAULT]
 head = head.js ../../../common/tests/unit/head_helpers.js ../../../common/tests/unit/head_http.js
 tail =
 skip-if = toolkit == 'android'
 
 [test_accounts.js]
 [test_client.js]
-skip-if = toolkit == 'gonk' && debug # times out, bug 1079405
+skip-if = toolkit == 'gonk' # times out, bug 1073639
 [test_credentials.js]
 [test_loginmgr_storage.js]
 skip-if = appname == 'b2g' # login manager storage only used on desktop.
 [test_manager.js]
 run-if = appname == 'b2g'
 reason = FxAccountsManager is only available for B2G for now
 [test_oauth_client.js]
 [test_profile_client.js]
--- a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py
+++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py
@@ -636,18 +636,18 @@ class DeviceManagerADB(DeviceManager):
         # Check to see if we can connect to device and run a simple command
         if self._checkCmd(["shell", "echo"]) is None:
             raise DMError("unable to connect to device")
 
     def _checkForRoot(self):
         # Check whether we _are_ root by default (some development boards work
         # this way, this is also the result of some relatively rare rooting
         # techniques)
-        data = self._runCmd(["shell", "id"]).output[0]
-        if data.find('uid=0(root)') >= 0:
+        proc = self._runCmd(["shell", "id"])
+        if proc.output and 'uid=0(root)' in proc.output[0]:
             self._haveRootShell = True
             # if this returns true, we don't care about su
             return
 
         # if root shell is not available, check if 'su' can be used to gain
         # root
         proc = self._runCmd(["shell", "su", "-c", "id"])
 
@@ -655,18 +655,17 @@ class DeviceManagerADB(DeviceManager):
         # password or triggers the Android SuperUser prompt
         start_time = time.time()
         retcode = None
         while (time.time() - start_time) <= 15 and retcode is None:
             retcode = proc.poll()
         if retcode is None: # still not terminated, kill
             proc.kill()
 
-        data = proc.output[0]
-        if data.find('uid=0(root)') >= 0:
+        if proc.output and 'uid=0(root)' in proc.output[0]:
             self._haveSu = True
 
         if self._runAdbAsRoot:
             self._adb_root()
 
     def _isUnzipAvailable(self):
         data = self._runCmd(["shell", "unzip"]).output
         for line in data:
--- a/toolkit/components/contentprefs/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/nsContentPrefService.js
@@ -1162,16 +1162,23 @@ ContentPrefService.prototype = {
     aDBFile.remove(false);
 
     let dbConnection = this._dbCreate(aDBService, aDBFile);
 
     return dbConnection;
   },
 
   _dbMigrate: function ContentPrefService__dbMigrate(aDBConnection, aOldVersion, aNewVersion) {
+    /**
+     * Migrations should follow the template rules in bug 1074817 comment 3 which are:
+     * 1. Migration should be incremental and non-breaking.
+     * 2. It should be idempotent because one can downgrade an upgrade again.
+     * On downgrade:
+     * 1. Decrement schema version so that upgrade runs the migrations again.
+     */
     aDBConnection.beginTransaction();
 
     try {
        /**
        * If the schema version is 0, that means it was never set, which means
        * the database was somehow created without the schema being applied, perhaps
        * because the system ran out of disk space (although we check for this
        * in _createDB) or because some other code created the database file without
@@ -1208,17 +1215,24 @@ ContentPrefService.prototype = {
     aDBConnection.executeSimpleSQL("DROP TABLE groupsOld");
   },
 
   _dbMigrate2To3: function ContentPrefService__dbMigrate2To3(aDBConnection) {
     this._dbCreateIndices(aDBConnection);
   },
 
   _dbMigrate3To4: function ContentPrefService__dbMigrate3To4(aDBConnection) {
-    aDBConnection.executeSimpleSQL("ALTER TABLE prefs ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0");
+    // Add timestamp column if it does not exist yet. This operation is idempotent.
+    try {
+      let stmt = aDBConnection.createStatement("SELECT timestamp FROM prefs");
+      stmt.finalize();
+    } catch (e) {
+      aDBConnection.executeSimpleSQL("ALTER TABLE prefs ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0");
+    }
+
     // To modify prefs_idx drop it and create again.
     aDBConnection.executeSimpleSQL("DROP INDEX IF EXISTS prefs_idx");
     this._dbCreateIndices(aDBConnection);
   },
 
   _parseGroupParam: function ContentPrefService__parseGroupParam(aGroup) {
     if (aGroup == null)
       return null;
--- a/toolkit/components/passwordmgr/content/passwordManager.xul
+++ b/toolkit/components/passwordmgr/content/passwordManager.xul
@@ -29,16 +29,17 @@
     <key key="&focusSearch2.key;" modifiers="accel" oncommand="FocusFilterBox();"/>
   </keyset>
 
   <popupset id="signonsTreeContextSet">
     <menupopup id="signonsTreeContextMenu"
            onpopupshowing="UpdateCopyPassword()">
       <menuitem id="context-copyusername"
                 label="&copyUsernameCmd.label;"
+                accesskey="&copyUsernameCmd.accesskey;"
                 oncommand="CopyUsername()"/>
       <menuitem id="context-copypassword"
                 label="&copyPasswordCmd.label;"
                 accesskey="&copyPasswordCmd.accesskey;"
                 oncommand="CopyPassword()"/>
     </menupopup>
   </popupset>
 
--- a/toolkit/content/tests/browser/browser.ini
+++ b/toolkit/content/tests/browser/browser.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-
+support-files = head.js
 [browser_autoscroll_disabled.js]
 skip-if = e10s # Bug ?????? - test touches content (getElementById on the content document)
 [browser_browserDrop.js]
 skip-if = buildapp == 'mulet'
 [browser_bug295977_autoscroll_overflow.js]
 skip-if = e10s # Bug 921935 - focusmanager issues with e10s
 [browser_bug594509.js]
 skip-if = e10s # Bug ?????? - intermittent crash of child process reported when run under e10s
--- a/toolkit/content/tests/browser/browser_findbar.js
+++ b/toolkit/content/tests/browser/browser_findbar.js
@@ -1,12 +1,58 @@
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://gre/modules/Timer.jsm", this);
 
+/**
+ * Makes sure that the findbar hotkeys (' and /) event listeners
+ * are added to the system event group and do not get blocked
+ * by calling stopPropagation on a keypress event on a page.
+ */
+add_task(function* test_hotkey_event_propagation() {
+  info("Ensure hotkeys are not affected by stopPropagation.");
+
+  // Opening new tab
+  let tab = yield promiseTestPageLoad();
+  let browser = gBrowser.getBrowserForTab(tab);
+  let findbar = gBrowser.getFindBar();
+
+  // Pressing these keys open the findbar.
+  const HOTKEYS = ["/", "'"];
+
+  // Checking if findbar appears when any hotkey is pressed.
+  for (let key of HOTKEYS) {
+    is(findbar.hidden, true, "Findbar is hidden now.");
+    gBrowser.selectedTab = tab;
+    yield promiseFocus();
+    EventUtils.sendChar(key, browser.contentWindow);
+    is(findbar.hidden, false, "Findbar should not be hidden.");
+    yield closeFindbarAndWait(findbar);
+  }
+
+  // Stop propagation for all keyboard events.
+  let window = browser.contentWindow;
+  let stopPropagation = function(e) { e.stopImmediatePropagation(); };
+  window.addEventListener("keydown", stopPropagation, true);
+  window.addEventListener("keypress", stopPropagation, true);
+  window.addEventListener("keyup", stopPropagation, true);
+
+  // Checking if findbar still appears when any hotkey is pressed.
+  for (let key of HOTKEYS) {
+    is(findbar.hidden, true, "Findbar is hidden now.");
+    gBrowser.selectedTab = tab;
+    yield promiseFocus();
+    EventUtils.sendChar(key, browser.contentWindow);
+    is(findbar.hidden, false, "Findbar should not be hidden.");
+    yield closeFindbarAndWait(findbar);
+  }
+
+  gBrowser.removeTab(tab);
+});
+
 add_task(function* test_not_found() {
   info("Check correct 'Phrase not found' on new tab");
 
   let tab = yield promiseTestPageLoad();
 
   // Search for the first word.
   yield promiseFindFinished("--- THIS SHOULD NEVER MATCH ---", false);
   let findbar = gBrowser.getFindBar();
@@ -98,8 +144,19 @@ function promiseFindFinished(searchText,
       onFindResult: foundOrTimedout
     };
     findbar.browser.finder.addResultListener(resultListener);
     findbar._find();
   });
 
   return deferred.promise;
 }
+
+/**
+ * A promise-like wrapper for the waitForFocus helper.
+ */
+function promiseFocus() {
+  return new Promise((resolve) => {
+    waitForFocus(function(){
+      resolve();
+    }, content);
+  });
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/head.js
@@ -0,0 +1,20 @@
+"use strict";
+
+/**
+ * A wrapper for the findbar's method "close", which is not synchronous
+ * because of animation.
+ */
+function closeFindbarAndWait(findbar) {
+  return new Promise((resolve) => {
+    if (findbar.hidden)
+      return resolve();
+    findbar.addEventListener("transitionend", function cont(aEvent) {
+      if (aEvent.propertyName != "visibility") {
+        return;
+      }
+      findbar.removeEventListener("transitionend", cont);
+      resolve();
+    });
+    findbar.close();
+  });
+}
--- a/toolkit/content/widgets/findbar.xml
+++ b/toolkit/content/widgets/findbar.xml
@@ -252,28 +252,34 @@
         <getter><![CDATA[
           if (!this._browser) {
             this._browser =
               document.getElementById(this.getAttribute("browserid"));
           }
           return this._browser;
         ]]></getter>
         <setter><![CDATA[
+          // A shortcut for the service.
+          let els = Components.classes["@mozilla.org/eventlistenerservice;1"].
+            getService(Components.interfaces.nsIEventListenerService);
+
           if (this._browser) {
-            this._browser.removeEventListener("keypress", this, false);
-            this._browser.removeEventListener("mouseup", this, false);
+            els.removeSystemEventListener(this._browser, "keypress", this,
+                                          false);
+            els.removeSystemEventListener(this._browser, "mouseup", this,
+                                          false);
             let finder = this._browser.finder;
             if (finder)
               finder.removeResultListener(this);
           }
 
           this._browser = val;
           if (this._browser) {
-            this._browser.addEventListener("keypress", this, false);
-            this._browser.addEventListener("mouseup", this, false);
+            els.addSystemEventListener(this._browser, "keypress", this, false);
+            els.addSystemEventListener(this._browser, "mouseup", this, false);
             this._browser.finder.addResultListener(this);
 
             this._findField.value = this._browser._lastSearchString;
             this.toggleHighlight(this.browser._lastSearchHighlight);
           }
           return val;
         ]]></setter>
       </property>
--- a/toolkit/devtools/server/actors/webaudio.js
+++ b/toolkit/devtools/server/actors/webaudio.js
@@ -10,17 +10,17 @@ const Services = require("Services");
 const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
 const events = require("sdk/event/core");
 const { on: systemOn, off: systemOff } = require("sdk/system/events");
 const protocol = require("devtools/server/protocol");
 const { CallWatcherActor, CallWatcherFront } = require("devtools/server/actors/call-watcher");
 const { ThreadActor } = require("devtools/server/actors/script");
 
 const { on, once, off, emit } = events;
-const { method, Arg, Option, RetVal } = protocol;
+const { types, method, Arg, Option, RetVal } = protocol;
 
 const AUDIO_GLOBALS = [
   "AudioContext", "AudioNode"
 ];
 
 const NODE_CREATION_METHODS = [
   "createBufferSource", "createMediaElementSource", "createMediaStreamSource",
   "createMediaStreamDestination", "createScriptProcessor", "createAnalyser",
@@ -104,16 +104,17 @@ const NODE_PROPERTIES = {
     "stream": { "MediaStream": true }
   }
 };
 
 /**
  * An Audio Node actor allowing communication to a specific audio node in the
  * Audio Context graph.
  */
+types.addActorType("audionode");
 let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({
   typeName: "audionode",
 
   /**
    * Create the Audio Node actor.
    *
    * @param DebuggerServerConnection conn
    *        The server connection.
@@ -284,17 +285,70 @@ let AudioNodeActor = exports.AudioNodeAc
    * corresponding to a property name and current value of the audio node.
    */
   getParams: method(function (param) {
     let props = Object.keys(NODE_PROPERTIES[this.type]);
     return props.map(prop =>
       ({ param: prop, value: this.getParam(prop), flags: this.getParamFlags(prop) }));
   }, {
     response: { params: RetVal("json") }
+  }),
+
+  /**
+   * Connects this audionode to another via `node.connect(dest)`.
+   */
+  connectNode: method(function (destActor, output, input) {
+    let srcNode = this.node.get();
+    let destNode = destActor.node.get();
+
+    if (srcNode === null || destNode === null) {
+      return CollectedAudioNodeError();
+    }
+
+    try {
+      // Connect via the unwrapped node, so we can call the
+      // patched method that fires the webaudio actor's `connect-node` event.
+      // Connect directly to the wrapped `destNode`, otherwise
+      // the patched method thinks this is a new node and won't be
+      // able to find it in `_nativeToActorID`.
+      XPCNativeWrapper.unwrap(srcNode).connect(destNode, output, input);
+    } catch (e) {
+      return constructError(e);
+    }
+  }, {
+    request: {
+      destActor: Arg(0, "audionode"),
+      output: Arg(1, "nullable:number"),
+      input: Arg(2, "nullable:number")
+    },
+    response: { error: RetVal("nullable:json") }
+  }),
+
+  /**
+   * Disconnects this audionode from all connections via `node.disconnect()`.
+   */
+  disconnect: method(function (destActor, output) {
+    let node = this.node.get();
+
+    if (node === null) {
+      return CollectedAudioNodeError();
+    }
+
+    try {
+      // Disconnect via the unwrapped node, so we can call the
+      // patched method that fires the webaudio actor's `disconnect` event.
+      XPCNativeWrapper.unwrap(node).disconnect(output);
+    } catch (e) {
+      return constructError(e);
+    }
+  }, {
+    request: { output: Arg(0, "nullable:number") },
+    response: { error: RetVal("nullable:json") }
   })
+
 });
 
 /**
  * The corresponding Front object for the AudioNodeActor.
  */
 let AudioNodeFront = protocol.FrontClass(AudioNodeActor, {
   initialize: function (client, form) {
     protocol.Front.prototype.initialize.call(this, client, form);
@@ -548,16 +602,17 @@ let WebAudioActor = exports.WebAudioActo
   },
 
   /**
    * Called when one audio node is connected to another.
    */
   _onConnectNode: function (source, dest) {
     let sourceActor = this._getActorByNativeID(source.id);
     let destActor = this._getActorByNativeID(dest.id);
+
     emit(this, "connect-node", {
       source: sourceActor,
       dest: destActor
     });
   },
 
   /**
    * Called when an audio node is connected to an audio param.
--- a/toolkit/devtools/webconsole/utils.js
+++ b/toolkit/devtools/webconsole/utils.js
@@ -1172,20 +1172,20 @@ let DebuggerEnvironmentSupport = {
     return aObj.names();
   },
 
   getProperty: function(aObj, aName)
   {
     // TODO: we should use getVariableDescriptor() here - bug 725815.
     let result = aObj.getVariable(aName);
     // FIXME: Need actual UI, bug 941287.
-    if (result.optimizedOut || result.missingArguments) {
+    if (result === undefined || result.optimizedOut || result.missingArguments) {
       return null;
     }
-    return result === undefined ? null : { value: result };
+    return { value: result };
   },
 };
 
 
 exports.JSPropertyProvider = DevToolsUtils.makeInfallible(JSPropertyProvider);
 })(WebConsoleUtils);
 
 ///////////////////////////////////////////////////////////////////////////////
--- a/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
+++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
@@ -28,8 +28,9 @@
 <!ENTITY      windowClose.key                 "w">
 <!ENTITY      focusSearch1.key                "f">
 <!ENTITY      focusSearch2.key                "k">
 
 <!ENTITY      copyPasswordCmd.label           "Copy Password">
 <!ENTITY      copyPasswordCmd.accesskey       "C">
 
 <!ENTITY      copyUsernameCmd.label           "Copy Username">
+<!ENTITY      copyUsernameCmd.accesskey       "U">
--- a/toolkit/mozapps/update/tests/chrome/utils.js
+++ b/toolkit/mozapps/update/tests/chrome/utils.js
@@ -149,16 +149,17 @@ const URL_HTTPS_UPDATE_XML = "https://ex
 const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
 
 const ADDON_ID_SUFFIX = "@appupdatetest.mozilla.org";
 const ADDON_PREP_DIR = "appupdateprep";
 // Preference for storing add-ons that are disabled by the tests to prevent them
 // from interefering with the tests.
 const PREF_DISABLEDADDONS = "app.update.test.disabledAddons";
 const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
+const PREF_EM_SILENT = "app.update.silent";
 const TEST_ADDONS = [ "appdisabled_1", "appdisabled_2",
                       "compatible_1", "compatible_2",
                       "noupdate_1", "noupdate_2",
                       "updatecompatibility_1", "updatecompatibility_2",
                       "updateversion_1", "updateversion_2",
                       "userdisabled_1", "userdisabled_2", "hotfix" ];
 
 var gURLData = URL_HOST + "/" + REL_PATH_DATA + "/";
@@ -906,16 +907,17 @@ function setupPrefs() {
   let extUpdateUrl = URL_HTTP_UPDATE_XML + "?addonID=%ITEM_ID%" +
                      "&platformVersion=" + getNewerPlatformVersion();
   Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, extUpdateUrl);
 
   Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0);
   Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0);
   Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true);
   Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix" + ADDON_ID_SUFFIX);
+  Services.prefs.setBoolPref(PREF_EM_SILENT, false);
 }
 
 /**
  * Restores files that were backed up for the tests and general file cleanup.
  */
 function resetFiles() {
   // Restore the backed up updater-settings.ini if it exists.
   let baseAppDir = getAppBaseDir();
@@ -1066,16 +1068,20 @@ function resetPrefs() {
 
   if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) {
 		Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT);
   }
 
   if (Services.prefs.prefHasUserValue(PREF_EM_HOTFIX_ID)) {
     Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID);
   }
+
+  if (Services.prefs.prefHasUserValue(PREF_EM_SILENT)) {
+    Services.prefs.clearUserPref(PREF_EM_SILENT);
+  }
 }
 
 function setupTimer(aTestTimeout) {
   gTestTimeout = aTestTimeout;
   if (gTimeoutTimer) {
     gTimeoutTimer.cancel();
     gTimeoutTimer = null;
   }
--- a/toolkit/webapps/LinuxNativeApp.js
+++ b/toolkit/webapps/LinuxNativeApp.js
@@ -161,17 +161,17 @@ NativeApp.prototype = {
       yield OS.File.removeDir(backupDir, { ignoreAbsent: true });
       yield OS.File.removeDir(updateDir, { ignoreAbsent: true });
     }
   }),
 
   _applyTempInstallation: Task.async(function*(aTmpDir, aInstallDir) {
     yield moveDirectory(aTmpDir, aInstallDir);
 
-    this._createSystemFiles(aInstallDir);
+    yield this._createSystemFiles(aInstallDir);
   }),
 
   _removeInstallation: function(keepProfile, aInstallDir) {
     let filesToRemove = [this.desktopINI];
 
     if (keepProfile) {
       for (let filePath of this.backupFiles) {
         filesToRemove.push(OS.Path.join(aInstallDir, filePath));
@@ -268,17 +268,17 @@ NativeApp.prototype = {
     writer.setString("Webapp", "UninstallMsg",
                      webappsBundle.formatStringFromName("uninstall.notification",
                                                         [this.appLocalizedName],
                                                         1));
     writer.setString("WebappRT", "InstallDir", this.runtimeFolder);
     writer.writeFile();
   },
 
-  _createSystemFiles: function(aInstallDir) {
+  _createSystemFiles: Task.async(function*(aInstallDir) {
     let webappsBundle = Services.strings.createBundle("chrome://global/locale/webapps.properties");
 
     let webapprtPath = OS.Path.join(aInstallDir, this.webapprt);
 
     // $XDG_DATA_HOME/applications/owa-<webappuniquename>.desktop
     let desktopINIfile = getFile(this.desktopINI);
     if (desktopINIfile.parent && !desktopINIfile.parent.exists()) {
       desktopINIfile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
@@ -301,18 +301,18 @@ NativeApp.prototype = {
       writer.setString("Desktop Entry", "Categories", categories);
 
     writer.setString("Desktop Entry", "Actions", "Uninstall;");
     writer.setString("Desktop Action Uninstall", "Name", webappsBundle.GetStringFromName("uninstall.label"));
     writer.setString("Desktop Action Uninstall", "Exec", webapprtPath + " -remove");
 
     writer.writeFile();
 
-    desktopINIfile.permissions = PERMS_FILE | OS.Constants.libc.S_IXUSR;
-  },
+    yield OS.File.setPermissions(desktopINIfile.path, { unixMode: PERMS_FILE | OS.Constants.libc.S_IXUSR });
+  }),
 
   /**
    * Process the icon from the imageStream as retrieved from
    * the URL by getIconForApp().
    *
    * @param aMimeType     ahe icon mimetype
    * @param aImageStream  the stream for the image data
    * @param aDir          the directory where the icon should be stored
--- a/toolkit/webapps/MacNativeApp.js
+++ b/toolkit/webapps/MacNativeApp.js
@@ -236,17 +236,17 @@ NativeApp.prototype = {
 
     let writer = Cc["@mozilla.org/xpcom/ini-processor-factory;1"].
                  getService(Ci.nsIINIParserFactory).
                  createINIParser(applicationINI).
                  QueryInterface(Ci.nsIINIParserWriter);
     writer.setString("Webapp", "Name", this.appLocalizedName);
     writer.setString("Webapp", "Profile", this.uniqueName);
     writer.writeFile();
-    applicationINI.permissions = PERMS_FILE;
+    yield OS.File.setPermissions(applicationINI.path, { unixMode: PERMS_FILE });
 
     // ${InstallDir}/Contents/Info.plist
     let infoPListContent = '<?xml version="1.0" encoding="UTF-8"?>\n\
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
 <plist version="1.0">\n\
   <dict>\n\
     <key>CFBundleDevelopmentRegion</key>\n\
     <string>English</string>\n\
--- a/toolkit/webapps/tests/head.js
+++ b/toolkit/webapps/tests/head.js
@@ -160,36 +160,36 @@ function TestAppInfo(aApp, aIsPackaged) 
 
     let xdg_data_home = Cc["@mozilla.org/process/environment;1"].
                         getService(Ci.nsIEnvironment).
                         get("XDG_DATA_HOME");
     if (!xdg_data_home) {
       xdg_data_home = OS.Path.join(OS.Constants.Path.homeDir, ".local", "share");
     }
 
-    let desktopINI = OS.Path.join(xdg_data_home, "applications",
+    this.desktopINI = OS.Path.join(xdg_data_home, "applications",
                                   "owa-" + this.uniqueName + ".desktop");
 
     this.installedFiles = [
       OS.Path.join(this.installPath, "webapp.json"),
       this.webappINI,
       this.iconFile,
       this.exePath,
-      desktopINI,
+      this.desktopINI,
     ];
     this.tempUpdatedFiles = [
       OS.Path.join(this.installPath, "update", "icon.png"),
       OS.Path.join(this.installPath, "update", "webapp.json"),
       OS.Path.join(this.installPath, "update", "webapp.ini"),
     ];
     this.updatedFiles = [
       OS.Path.join(this.installPath, "webapp.json"),
       this.webappINI,
       this.iconFile,
-      desktopINI,
+      this.desktopINI,
     ];
 
     if (this.isPackaged) {
       let appZipPath = OS.Path.join(this.installPath, "application.zip");
       this.installedFiles.push(appZipPath);
       this.tempUpdatedFiles.push(appZipPath);
       this.updatedFiles.push(appZipPath);
     }
@@ -204,17 +204,17 @@ function TestAppInfo(aApp, aIsPackaged) 
       }
 
       yield OS.File.removeDir(this.cacheRoot, { ignoreAbsent: true });
 
       yield OS.File.removeDir(this.profileRoot, { ignoreAbsent: true });
 
       yield OS.File.removeDir(this.installPath, { ignoreAbsent: true });
 
-      yield OS.File.remove(desktopINI, { ignoreAbsent: true });
+      yield OS.File.remove(this.desktopINI, { ignoreAbsent: true });
     });
   } else if (WIN) {
     this.installPath = OS.Path.join(OS.Constants.Path.winAppDataDir,
                                     this.uniqueName);
     this.exePath = OS.Path.join(this.installPath, aApp.name + ".exe");
 
     this.iconFile = OS.Path.join(this.installPath, "chrome", "icons", "default", "default.ico");
 
--- a/toolkit/webapps/tests/test_hosted.xul
+++ b/toolkit/webapps/tests/test_hosted.xul
@@ -101,16 +101,25 @@ let runTest = Task.async(function*() {
   ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
   ok((yield checkFiles(testAppInfo.tempUpdatedFiles)), "Files correctly written in the update subdirectory");
 
   yield nativeApp.applyUpdate(app);
   while (!WebappOSUtils.isLaunchable(app)) {
     yield wait(1000);
   }
   ok(true, "App launchable");
+
+  if (MAC) {
+    stat = yield OS.File.stat(testAppInfo.webappINI);
+    is(stat.unixMode, 0o644, "Configuration file permissions correct");
+  } else if (LINUX) {
+    stat = yield OS.File.stat(testAppInfo.desktopINI);
+    is(stat.unixMode, 0o744, "Configuration file permissions correct");
+  }
+
   ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
   ok(!(yield OS.File.exists(OS.Path.join(testAppInfo.installPath, "update"))), "Update directory removed");
   ok((yield checkDateHigherThan(testAppInfo.updatedFiles, installTime)), "Modification date higher");
 
   stat = yield OS.File.stat(testAppInfo.installPath);
   installTime = stat.lastModificationDate;
 
   // Wait one second, otherwise the last modification date is the same.
--- a/toolkit/webapps/tests/test_packaged.xul
+++ b/toolkit/webapps/tests/test_packaged.xul
@@ -114,16 +114,25 @@ let runTest = Task.async(function*() {
   ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
   ok((yield checkFiles(testAppInfo.tempUpdatedFiles)), "Files correctly written in the update subdirectory");
 
   yield nativeApp.applyUpdate(app);
   while (!WebappOSUtils.isLaunchable(app)) {
     yield wait(1000);
   }
   ok(true, "App launchable");
+
+  if (MAC) {
+    stat = yield OS.File.stat(testAppInfo.webappINI);
+    is(stat.unixMode, 0o644, "Configuration file permissions correct");
+  } else if (LINUX) {
+    stat = yield OS.File.stat(testAppInfo.desktopINI);
+    is(stat.unixMode, 0o744, "Configuration file permissions correct");
+  }
+
   ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
   ok(!(yield OS.File.exists(OS.Path.join(testAppInfo.installPath, "update"))), "Update directory removed");
   ok((yield checkDateHigherThan(testAppInfo.updatedFiles, installTime)), "Modification date higher");
 
   stat = yield OS.File.stat(testAppInfo.installPath);
   installTime = stat.lastModificationDate;
 
   // Wait one second, otherwise the last modification date is the same.
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -761,28 +761,26 @@ ParseManifest(NSLocationType aType, File
           LogMessageWithContext(aFile, line,
                                 "Chrome registry isn't available yet.");
           continue;
         }
       }
 
       (nsChromeRegistry::gChromeRegistry->*(directive->regfunc))(
         chromecx, line, argv, platform, contentAccessible);
-    } else if (directive->mgrfunc && (directive->ischrome || !aChromeOnly)) {
+    } else if (directive->ischrome || !aChromeOnly) {
       if (directive->isContract) {
         CachedDirective* cd = contracts.AppendElement();
         cd->lineno = line;
         cd->argv[0] = argv[0];
         cd->argv[1] = argv[1];
       } else {
         (nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))(
           mgrcx, line, argv);
       }
-    } else {
-      LogMessageWithContext(aFile, line, "No valid manifest directive.");
     }
   }
 
   for (uint32_t i = 0; i < contracts.Length(); ++i) {
     CachedDirective& d = contracts[i];
     nsComponentManagerImpl::gComponentManager->ManifestContract(mgrcx,
                                                                 d.lineno,
                                                                 d.argv);