merge fx-team to m-c
authorTim Taubert <tim.taubert@gmx.de>
Thu, 26 Jan 2012 08:45:50 +0100
changeset 87833 402b394b66238c926edef76a349cdc633120d058
parent 87832 dca6fb65e46b4501e60ebce82b9cb6a34af9caff (current diff)
parent 87824 c6a3d396b0cd241f0f49095486e6de7a8de2c52d (diff)
child 87881 f20f2b7c93cb07a51f739c2242cc4d474a81b9f8
child 87882 bff640abf40ccbc4ee850c1db1d1a7c48ce1c1ce
push id674
push userffxbld
push dateTue, 13 Mar 2012 21:17:50 +0000
treeherdermozilla-beta@e3c4c92dec31 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
first release with
nightly linux32
402b394b6623 / 12.0a1 / 20120126031113 / files
nightly linux64
402b394b6623 / 12.0a1 / 20120126031113 / files
nightly mac
402b394b6623 / 12.0a1 / 20120126031113 / files
nightly win32
402b394b6623 / 12.0a1 / 20120126031113 / files
nightly win64
402b394b6623 / 12.0a1 / 20120126031113 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge fx-team to m-c
browser/base/content/browser.js
dom/interfaces/traversal/nsIDOMDocumentTraversal.idl
mobile/android/base/SyncPreference.java.in
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -171,17 +171,18 @@
             <menuitem id="appmenu_printSetup"
                       label="&printSetupCmd.label;"
                       command="cmd_pageSetup"/>
           </menupopup>
       </splitmenu>
       <menuseparator class="appmenu-menuseparator"/>
       <menu id="appmenu_webDeveloper"
             label="&appMenuWebDeveloper.label;">
-        <menupopup id="appmenu_webDeveloper_popup">
+        <menupopup id="appmenu_webDeveloper_popup"
+                   onpopupshowing="onWebDeveloperMenuShowing();">
           <menuitem id="appmenu_webConsole"
                     label="&webConsoleCmd.label;"
                     type="checkbox"
                     command="Tools:WebConsole"
                     key="key_webConsole"/>
           <menuitem id="appmenu_pageInspect"
                     hidden="true"
                     label="&inspectMenu.label;"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -526,17 +526,18 @@
                         accesskey="&syncSyncNowItem.accesskey;"
                         observes="sync-syncnow-state"
                         oncommand="gSyncUI.doSync(event);"/>
 #endif
               <menuseparator id="devToolsSeparator"/>
               <menu id="webDeveloperMenu"
                     label="&webDeveloperMenu.label;"
                     accesskey="&webDeveloperMenu.accesskey;">
-                <menupopup id="menuWebDeveloperPopup">
+                <menupopup id="menuWebDeveloperPopup"
+                           onpopupshowing="onWebDeveloperMenuShowing();">
                   <menuitem id="webConsole"
                             type="checkbox"
                             label="&webConsoleCmd.label;"
                             accesskey="&webConsoleCmd.accesskey;"
                             key="key_webConsole"
                             command="Tools:WebConsole"/>
                   <menuitem id="menu_pageinspect"
                             type="checkbox"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -9066,16 +9066,21 @@ var StyleEditor = {
     let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
                                               CHROME_WINDOW_FLAGS,
                                               contentWindow);
     chromeWindow.focus();
     return chromeWindow;
   }
 };
 
+function onWebDeveloperMenuShowing() {
+  document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
+}
+
+
 XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
 #ifdef XP_WIN
   // Only show resizers on Windows 2000 and XP
   let sysInfo = Components.classes["@mozilla.org/system-info;1"]
                           .getService(Components.interfaces.nsIPropertyBag2);
   return parseFloat(sysInfo.getProperty("version")) < 6;
 #else
   return false;
@@ -9140,15 +9145,16 @@ var MousePosTracker = {
       if (listener.onMouseEnter)
         listener.onMouseEnter();
     } else {
       if (listener.onMouseLeave)
         listener.onMouseLeave();
     }
   }
 };
+
 function focusNextFrame(event) {
   let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
   let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;
   let element = fm.moveFocus(window, null, dir, fm.FLAG_BYKEY);
   if (element.ownerDocument == document)
     focusAndSelectUrlBar();
 }
--- a/browser/components/tabview/iq.js
+++ b/browser/components/tabview/iq.js
@@ -736,16 +736,21 @@ iQClass.prototype = {
       let handler = func;
       if (elem.iQEventData && elem.iQEventData[type]) {
         let count = elem.iQEventData[type].length;
         for (let a = 0; a < count; a++) {
           let pair = elem.iQEventData[type][a];
           if (pair.original == func) {
             handler = pair.modified;
             elem.iQEventData[type].splice(a, 1);
+            if (!elem.iQEventData[type].length) {
+              delete elem.iQEventData[type];
+              if (!Object.keys(elem.iQEventData).length)
+                delete elem.iQEventData;
+            }
             break;
           }
         }
       }
 
       elem.removeEventListener(type, handler, false);
     }
 
@@ -760,20 +765,20 @@ iQClass.prototype = {
       let elem = this[i];
 
       for (let j = 0; j < elem.childElementCount; j++)
         iQ(elem.children[j]).unbindAll();
 
       if (!elem.iQEventData)
         continue;
 
-      for (let type in elem.iQEventData) {
-        while (elem.iQEventData[type].length)
+      Object.keys(elem.iQEventData).forEach(function (type) {
+        while (elem.iQEventData && elem.iQEventData[type])
           this.unbind(type, elem.iQEventData[type][0].original);
-      }
+      }, this);
     }
 
     return this;
   }
 };
 
 // ----------
 // Create various event aliases
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -1547,18 +1547,16 @@ HUD_SERVICE.prototype =
 
     let hudId = "hud_" + nBox.id;
     let hudRef = this.hudReferences[hudId];
 
     if (!aAnimated || hudRef.consolePanel) {
       this.disableAnimation(hudId);
     }
 
-    chromeDocument.getElementById("Tools:WebConsole").setAttribute("checked", "true");
-
     // Create a processing instruction for GCLIs CSS stylesheet, but only if
     // we don't have one for this document. Also record the context we're
     // adding this for so we know when to remove it.
     let procInstr = aContext.ownerDocument.gcliCssProcInstr;
     if (!procInstr) {
       procInstr = aContext.ownerDocument.createProcessingInstruction(
               "xml-stylesheet",
               "href='chrome://browser/skin/devtools/gcli.css' type='text/css'");
@@ -1598,18 +1596,16 @@ HUD_SERVICE.prototype =
       browser.webProgress.removeProgressListener(hud.progressListener);
       delete hud.progressListener;
 
       this.unregisterDisplay(hudId);
 
       window.focus();
     }
 
-    chromeDocument.getElementById("Tools:WebConsole").setAttribute("checked", "false");
-
     // Remove this context from the list of contexts that need the GCLI CSS
     // processing instruction and then remove the processing instruction if it
     // isn't needed any more.
     let procInstr = aContext.ownerDocument.gcliCssProcInstr;
     if (procInstr) {
       procInstr.contexts = procInstr.contexts.filter(function(id) {
         return id !== hudId;
       });
--- a/configure.in
+++ b/configure.in
@@ -332,16 +332,17 @@ if test -n "$gonkdir" ; then
         HOST_CXXFLAGS=" "
     fi
     if test -z "$HOST_LDFLAGS" ; then
         HOST_LDFLAGS=" "
     fi
 
     AC_DEFINE(ANDROID)
     AC_DEFINE(HAVE_SYS_UIO_H)
+    AC_DEFINE(HAVE_PTHREADS)
     CROSS_COMPILE=1
     MOZ_CHROME_FILE_FORMAT=omni
     ZLIB_DIR=yes
     direct_nspr_config=1
 else
 case "$target" in
 *-android*|*-linuxandroid*)
     if test -z "$android_ndk" ; then
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -68,16 +68,17 @@
 #include "mozilla/css/Loader.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIScriptRuntime.h"
 #include "nsCOMArray.h"
 
 #include "nsGUIEvent.h"
 #include "nsAsyncDOMEvent.h"
+#include "nsIDOMNodeFilter.h"
 
 #include "nsIDOMStyleSheet.h"
 #include "nsDOMAttribute.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMDocumentXBL.h"
 #include "mozilla/FunctionTimer.h"
 #include "nsGenericElement.h"
@@ -5019,67 +5020,73 @@ nsDocument::CreateRange(nsIDOMRange** aR
   range.forget(aReturn);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
                                PRUint32 aWhatToShow,
                                nsIDOMNodeFilter *aFilter,
-                               bool aEntityReferenceExpansion,
+                               PRUint8 aOptionalArgc,
                                nsIDOMNodeIterator **_retval)
 {
   *_retval = nsnull;
 
+  if (!aOptionalArgc) {
+    aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
+  }
+
   if (!aRoot)
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 
   nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
   NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 
   nsNodeIterator *iterator = new nsNodeIterator(root,
                                                 aWhatToShow,
-                                                aFilter,
-                                                aEntityReferenceExpansion);
+                                                aFilter);
   NS_ENSURE_TRUE(iterator, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(*_retval = iterator);
 
-  return NS_OK; 
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
                              PRUint32 aWhatToShow,
                              nsIDOMNodeFilter *aFilter,
-                             bool aEntityReferenceExpansion,
+                             PRUint8 aOptionalArgc,
                              nsIDOMTreeWalker **_retval)
 {
   *_retval = nsnull;
 
+  if (!aOptionalArgc) {
+    aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
+  }
+
   if (!aRoot)
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 
   nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
   NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 
   nsTreeWalker* walker = new nsTreeWalker(root,
                                           aWhatToShow,
-                                          aFilter,
-                                          aEntityReferenceExpansion);
+                                          aFilter);
   NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(*_retval = walker);
 
   return NS_OK;
 }
 
 
--- a/content/base/src/nsNodeIterator.cpp
+++ b/content/base/src/nsNodeIterator.cpp
@@ -165,19 +165,18 @@ void nsNodeIterator::NodePointer::MoveBa
 }
 
 /*
  * Factories, constructors and destructors
  */
 
 nsNodeIterator::nsNodeIterator(nsINode *aRoot,
                                PRUint32 aWhatToShow,
-                               nsIDOMNodeFilter *aFilter,
-                               bool aExpandEntityReferences) :
-    nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
+                               nsIDOMNodeFilter *aFilter) :
+    nsTraversal(aRoot, aWhatToShow, aFilter),
     mDetached(false),
     mPointer(mRoot, true)
 {
     aRoot->AddMutationObserver(this);
 }
 
 nsNodeIterator::~nsNodeIterator()
 {
@@ -242,17 +241,17 @@ NS_IMETHODIMP nsNodeIterator::GetFilter(
     NS_IF_ADDREF(*aFilter = mFilter);
 
     return NS_OK;
 }
 
 /* readonly attribute boolean expandEntityReferences; */
 NS_IMETHODIMP nsNodeIterator::GetExpandEntityReferences(bool *aExpandEntityReferences)
 {
-    *aExpandEntityReferences = mExpandEntityReferences;
+    *aExpandEntityReferences = false;
     return NS_OK;
 }
 
 /* nsIDOMNode nextNode ()  raises (DOMException); */
 NS_IMETHODIMP nsNodeIterator::NextNode(nsIDOMNode **_retval)
 {
     return NextOrPrevNode(&NodePointer::MoveToNext, _retval);
 }
--- a/content/base/src/nsNodeIterator.h
+++ b/content/base/src/nsNodeIterator.h
@@ -58,18 +58,17 @@ class nsNodeIterator : public nsIDOMNode
                        public nsStubMutationObserver2
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIDOMNODEITERATOR
 
     nsNodeIterator(nsINode *aRoot,
                    PRUint32 aWhatToShow,
-                   nsIDOMNodeFilter *aFilter,
-                   bool aExpandEntityReferences);
+                   nsIDOMNodeFilter *aFilter);
     virtual ~nsNodeIterator();
 
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER2_ATTRIBUTECHILDREMOVED
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNodeIterator, nsIDOMNodeIterator)
 
 private:
--- a/content/base/src/nsTraversal.cpp
+++ b/content/base/src/nsTraversal.cpp
@@ -44,22 +44,20 @@
 #include "nsDOMError.h"
 
 #include "nsIContent.h"
 
 #include "nsGkAtoms.h"
 
 nsTraversal::nsTraversal(nsINode *aRoot,
                          PRUint32 aWhatToShow,
-                         nsIDOMNodeFilter *aFilter,
-                         bool aExpandEntityReferences) :
+                         nsIDOMNodeFilter *aFilter) :
     mRoot(aRoot),
     mWhatToShow(aWhatToShow),
     mFilter(aFilter),
-    mExpandEntityReferences(aExpandEntityReferences),
     mInAcceptNode(false)
 {
     NS_ASSERTION(aRoot, "invalid root in call to nsTraversal constructor");
 }
 
 nsTraversal::~nsTraversal()
 {
     /* destructor code */
--- a/content/base/src/nsTraversal.h
+++ b/content/base/src/nsTraversal.h
@@ -49,25 +49,23 @@
 class nsINode;
 class nsIDOMNodeFilter;
 
 class nsTraversal
 {
 public:
     nsTraversal(nsINode *aRoot,
                 PRUint32 aWhatToShow,
-                nsIDOMNodeFilter *aFilter,
-                bool aExpandEntityReferences);
+                nsIDOMNodeFilter *aFilter);
     virtual ~nsTraversal();
 
 protected:
     nsCOMPtr<nsINode> mRoot;
     PRUint32 mWhatToShow;
     nsCOMPtr<nsIDOMNodeFilter> mFilter;
-    bool mExpandEntityReferences;
     bool mInAcceptNode;
 
     /*
      * Tests if and how a node should be filtered. Uses mWhatToShow and
      * mFilter to test the node.
      * @param aNode     Node to test
      * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
      * @returns         Errorcode
--- a/content/base/src/nsTreeWalker.cpp
+++ b/content/base/src/nsTreeWalker.cpp
@@ -53,19 +53,18 @@
 #include "nsContentUtils.h"
 
 /*
  * Factories, constructors and destructors
  */
 
 nsTreeWalker::nsTreeWalker(nsINode *aRoot,
                            PRUint32 aWhatToShow,
-                           nsIDOMNodeFilter *aFilter,
-                           bool aExpandEntityReferences) :
-    nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
+                           nsIDOMNodeFilter *aFilter) :
+    nsTraversal(aRoot, aWhatToShow, aFilter),
     mCurrentNode(aRoot)
 {
 }
 
 nsTreeWalker::~nsTreeWalker()
 {
     /* destructor code */
 }
@@ -122,17 +121,17 @@ NS_IMETHODIMP nsTreeWalker::GetFilter(ns
 
     return NS_OK;
 }
 
 /* readonly attribute boolean expandEntityReferences; */
 NS_IMETHODIMP
 nsTreeWalker::GetExpandEntityReferences(bool *aExpandEntityReferences)
 {
-    *aExpandEntityReferences = mExpandEntityReferences;
+    *aExpandEntityReferences = false;
     return NS_OK;
 }
 
 /* attribute nsIDOMNode currentNode; */
 NS_IMETHODIMP nsTreeWalker::GetCurrentNode(nsIDOMNode * *aCurrentNode)
 {
     if (mCurrentNode) {
         return CallQueryInterface(mCurrentNode, aCurrentNode);
--- a/content/base/src/nsTreeWalker.h
+++ b/content/base/src/nsTreeWalker.h
@@ -58,18 +58,17 @@ class nsIDOMNodeFilter;
 class nsTreeWalker : public nsIDOMTreeWalker, public nsTraversal
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIDOMTREEWALKER
 
     nsTreeWalker(nsINode *aRoot,
                  PRUint32 aWhatToShow,
-                 nsIDOMNodeFilter *aFilter,
-                 bool aExpandEntityReferences);
+                 nsIDOMNodeFilter *aFilter);
     virtual ~nsTreeWalker();
 
     NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeWalker)
 
 private:
     nsCOMPtr<nsINode> mCurrentNode;
 
     /*
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -537,16 +537,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug707142.html \
 		file_bug707142_baseline.json \
 		file_bug707142_bom.json \
 		file_bug707142_utf-16.json \
 		test_reentrant_flush.html \
 		test_bug708620.html \
 		file_bug708620.html \
 		file_bug708620-2.html \
+		test_bug698384.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug698384.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+  <!--
+    https://bugzilla.mozilla.org/show_bug.cgi?id=698384
+  -->
+  <head>
+    <title>Test for Bug 698384</title>
+    <script type="text/javascript"
+      src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script src="/tests/SimpleTest/EventUtils.js"
+      type="text/javascript"></script>
+    <link rel="stylesheet" type="text/css"
+      href="/tests/SimpleTest/test.css" />
+  </head>
+  <body onload="runTests();">
+    <a target="_blank"
+      href="https://bugzilla.mozilla.org/show_bug.cgi?id=698384">
+      Mozilla Bug 698384</a>
+    <p id="display"></p>
+    <div id="content" style="display: none"></div>
+    <pre id="test">
+      <script type="text/javascript">
+        /*
+          Checks to see if default parameter handling is correct when 0, 1
+          or 2 parameters are passed.
+
+          If one is only passed, aFilter should default to null
+          If none are passed, aFilter should be null and aWhatToShow should
+          be NodeFilter.SHOW_ALL
+        */
+        SimpleTest.waitForExplicitFinish();
+
+        var content = $('content'),
+            ni;
+
+        content.innerHTML = ('<span id="A"><\/span><span id="B"><\/span>'
+          + '<span id="C"><\/span>');
+
+        function runTests() {
+
+          // Test NodeIterator when no optional arguments are given
+          ni = document.createNodeIterator(content);
+          is(ni.whatToShow, NodeFilter.SHOW_ALL, "whatToShow should be " +
+            "NodeFilter.SHOW_ALL when both " +
+            " optionals are not given");
+          is(ni.filter, null, "filter should be defaulted to null when both " +
+            " optionals are not given");
+
+          // Test NodeIterator when first optional is passed
+          ni = document.createNodeIterator(content, NodeFilter.SHOW_ELEMENT);
+          is(ni.filter, null, "filter should be defaulted to null when only " +
+            " first argument is passed");
+          is(ni.whatToShow, NodeFilter.SHOW_ELEMENT, "whatToShow should " +
+            "properly be set to NodeFilter.SHOW_ELEMENT when whatToShow is " +
+            "provided and filter is not");
+
+          SimpleTest.finish();
+        }
+      </script>
+    </pre>
+  </body>
+</html>
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -811,17 +811,17 @@ nsDOMWindowUtils::GarbageCollect(nsICycl
   SAMPLE_LABEL("GC", "GarbageCollect");
   // Always permit this in debug builds.
 #ifndef DEBUG
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 #endif
 
-  nsJSContext::GarbageCollectNow();
+  nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS);
   nsJSContext::CycleCollectNow(aListener);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener *aListener)
 {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2267,17 +2267,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       mArgumentsOrigin = nsnull;
     }
 
     // Give the new inner window our chrome event handler (since it
     // doesn't have one).
     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
   }
 
-  mContext->GC();
+  mContext->GC(js::gcreason::SET_NEW_DOCUMENT);
   mContext->DidInitializeContext();
 
   if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
     // We should probably notify. However if this is the, arguably bad,
     // situation when we're creating a temporary non-chrome-about-blank
     // document in a chrome docshell, don't notify just yet. Instead wait
     // until we have a real chrome doc.
     nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
@@ -2424,17 +2424,17 @@ nsGlobalWindow::SetDocShell(nsIDocShell*
       // We got no new document after someone called
       // SetArguments(), drop our reference to the arguments.
       mArguments = nsnull;
       mArgumentsLast = nsnull;
       mArgumentsOrigin = nsnull;
     }
 
     if (mContext) {
-      mContext->GC();
+      mContext->GC(js::gcreason::SET_DOC_SHELL);
       mContext->FinalizeContext();
       mContext = nsnull;
     }
 
 #ifdef DEBUG
     nsCycleCollector_DEBUG_shouldBeFreed(mContext);
     nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
 #endif
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -38,16 +38,17 @@
 #ifndef nsIScriptContext_h__
 #define nsIScriptContext_h__
 
 #include "nscore.h"
 #include "nsStringGlue.h"
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsIProgrammingLanguage.h"
+#include "jsfriendapi.h"
 #include "jspubtd.h"
 
 class nsIScriptGlobalObject;
 class nsIScriptSecurityManager;
 class nsIPrincipal;
 class nsIAtom;
 class nsIArray;
 class nsIVariant;
@@ -349,17 +350,17 @@ public:
   virtual void FinalizeContext() = 0;
 
   /**
    * For garbage collected systems, do a synchronous collection pass.
    * May be a no-op on other systems
    *
    * @return NS_OK if the method is successful
    */
-  virtual void GC() = 0;
+  virtual void GC(js::gcreason::Reason aReason) = 0;
 
   /**
    * Inform the context that a script was evaluated.
    * A GC may be done if "necessary."
    * This call is necessary if script evaluation is done
    * without using the EvaluateScript method.
    * @param aTerminated If true then call termination function if it was 
    *    previously set. Within DOM this will always be true, but outside 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -198,17 +198,17 @@ public:
 
 NS_IMPL_ISUPPORTS1(nsMemoryPressureObserver, nsIObserver)
 
 NS_IMETHODIMP
 nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                   const PRUnichar* aData)
 {
   if (sGCOnMemoryPressure) {
-    nsJSContext::GarbageCollectNow(true);
+    nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking);
     nsJSContext::CycleCollectNow();
   }
   return NS_OK;
 }
 
 class nsRootedJSValueArray {
 public:
   explicit nsRootedJSValueArray(JSContext *cx) : avr(cx, vals.Length(), vals.Elements()) {}
@@ -1106,17 +1106,17 @@ nsJSContext::DestroyJSContext()
   // Clear our entry in the JSContext, bugzilla bug 66413
   ::JS_SetContextPrivate(mContext, nsnull);
 
   // Unregister our "javascript.options.*" pref-changed callback.
   Preferences::UnregisterCallback(JSOptionChangedCallback,
                                   js_options_dot_str, this);
 
   if (mGCOnDestruction) {
-    PokeGC();
+    PokeGC(js::gcreason::NSJSCONTEXT_DESTROY);
   }
         
   // Let xpconnect destroy the JSContext when it thinks the time is right.
   nsIXPConnect *xpc = nsContentUtils::XPConnect();
   if (xpc) {
     xpc->ReleaseJSContext(mContext, true);
   } else {
     ::JS_DestroyContextNoGC(mContext);
@@ -3215,17 +3215,17 @@ nsJSContext::ScriptExecuted()
 {
   ScriptEvaluated(!::JS_IsRunning(mContext));
 
   return NS_OK;
 }
 
 //static
 void
-nsJSContext::GarbageCollectNow(bool shrinkingGC)
+nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind)
 {
   NS_TIME_FUNCTION_MIN(1.0);
   SAMPLE_LABEL("GC", "GarbageCollectNow");
 
   KillGCTimer();
   KillShrinkGCBuffersTimer();
 
   // Reset sPendingLoadCount in case the timer that fired was a
@@ -3233,17 +3233,17 @@ nsJSContext::GarbageCollectNow(bool shri
   // documents were loading. If this happens we're waiting for a
   // document that is taking a long time to load, and we effectively
   // ignore the fact that the currently loading documents are still
   // loading and move on as if they weren't.
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
 
   if (nsContentUtils::XPConnect()) {
-    nsContentUtils::XPConnect()->GarbageCollect(shrinkingGC);
+    nsContentUtils::XPConnect()->GarbageCollect(reason, gckind);
   }
 }
 
 //static
 void
 nsJSContext::ShrinkGCBuffersNow()
 {
   NS_TIME_FUNCTION_MIN(1.0);
@@ -3271,17 +3271,17 @@ nsJSContext::CycleCollectNow(nsICycleCol
 
   PRUint32 suspected = nsCycleCollector_suspectedCount();
   PRUint32 collected = nsCycleCollector_collect(aListener);
   sCCollectedWaitingForGC += collected;
 
   // If we collected a substantial amount of cycles, poke the GC since more objects
   // might be unreachable now.
   if (sCCollectedWaitingForGC > 250) {
-    PokeGC();
+    PokeGC(js::gcreason::CC_WAITING);
   }
 
   PRTime now = PR_Now();
 
   if (sLastCCEndTime) {
     PRUint32 timeBetween = (PRUint32)(start - sLastCCEndTime) / PR_USEC_PER_SEC;
     Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_TIME_BETWEEN, timeBetween);
   }
@@ -3310,17 +3310,18 @@ nsJSContext::CycleCollectNow(nsICycleCol
 }
 
 // static
 void
 GCTimerFired(nsITimer *aTimer, void *aClosure)
 {
   NS_RELEASE(sGCTimer);
 
-  nsJSContext::GarbageCollectNow();
+  uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
+  nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCNormal);
 }
 
 void
 ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
 {
   NS_RELEASE(sShrinkGCBuffersTimer);
 
   nsJSContext::ShrinkGCBuffersNow();
@@ -3354,38 +3355,38 @@ nsJSContext::LoadEnd()
   // need to be), so make sure we don't make it wrap backwards here.
   if (sPendingLoadCount > 0) {
     --sPendingLoadCount;
     return;
   }
 
   // Its probably a good idea to GC soon since we have finished loading.
   sLoadingInProgress = false;
-  PokeGC();
+  PokeGC(js::gcreason::LOAD_END);
 }
 
 // static
 void
-nsJSContext::PokeGC()
+nsJSContext::PokeGC(js::gcreason::Reason aReason)
 {
   if (sGCTimer) {
     // There's already a timer for GC'ing, just return
     return;
   }
 
   CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);
 
   if (!sGCTimer) {
     // Failed to create timer (probably because we're in XPCOM shutdown)
     return;
   }
 
   static bool first = true;
 
-  sGCTimer->InitWithFuncCallback(GCTimerFired, nsnull,
+  sGCTimer->InitWithFuncCallback(GCTimerFired, reinterpret_cast<void *>(aReason),
                                  first
                                  ? NS_FIRST_GC_DELAY
                                  : NS_GC_DELAY,
                                  nsITimer::TYPE_ONE_SHOT);
 
   first = false;
 }
 
@@ -3468,19 +3469,19 @@ nsJSContext::KillCCTimer()
   if (sCCTimer) {
     sCCTimer->Cancel();
 
     NS_RELEASE(sCCTimer);
   }
 }
 
 void
-nsJSContext::GC()
+nsJSContext::GC(js::gcreason::Reason aReason)
 {
-  PokeGC();
+  PokeGC(aReason);
 }
 
 static void
 DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
 {
   NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
 
   if (sPostGCEventsToConsole) {
@@ -3508,17 +3509,17 @@ DOMGCFinishedCallback(JSRuntime *rt, JSC
     nsJSContext::KillGCTimer();
 
     // If this is a compartment GC, restart it. We still want
     // a full GC to happen. Compartment GCs usually happen as a
     // result of last-ditch or MaybeGC. In both cases its
     // probably a time of heavy activity and we want to delay
     // the full GC, but we do want it to happen eventually.
     if (comp) {
-      nsJSContext::PokeGC();
+      nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
 
       // We poked the GC, so we can kill any pending CC here.
       nsJSContext::KillCCTimer();
     }
   } else {
     // If this was a full GC, poke the CC to run soon.
     if (!comp) {
       sGCHasRun = true;
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -36,20 +36,22 @@
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsJSEnvironment_h
 #define nsJSEnvironment_h
 
 #include "nsIScriptContext.h"
 #include "nsIScriptRuntime.h"
 #include "nsCOMPtr.h"
 #include "jsapi.h"
+#include "jsfriendapi.h"
 #include "nsIObserver.h"
 #include "nsIXPCScriptNotify.h"
 #include "prtime.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsIXPConnect.h"
 
 class nsIXPConnectJSObjectHolder;
 class nsRootedJSValueArray;
 class nsScriptNameSpaceManager;
 namespace mozilla {
 template <class> class Maybe;
 }
 
@@ -174,31 +176,31 @@ public:
   virtual void EnterModalState();
   virtual void LeaveModalState();
 
   NS_DECL_NSIXPCSCRIPTNOTIFY
 
   static void LoadStart();
   static void LoadEnd();
 
-  static void GarbageCollectNow(bool shrinkingGC = false);
+  static void GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind = nsGCNormal);
   static void ShrinkGCBuffersNow();
   static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull);
 
-  static void PokeGC();
+  static void PokeGC(js::gcreason::Reason aReason);
   static void KillGCTimer();
 
   static void PokeShrinkGCBuffers();
   static void KillShrinkGCBuffersTimer();
 
   static void PokeCC();
   static void MaybePokeCC();
   static void KillCCTimer();
 
-  virtual void GC();
+  virtual void GC(js::gcreason::Reason aReason);
 
 protected:
   nsresult InitializeExternalClasses();
 
   // Helper to convert xpcom datatypes to jsvals.
   nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
                                    JSObject *aScope,
                                    PRUint32 *aArgc,
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -61,17 +61,17 @@ interface nsIDOMLocation;
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(5c3bff4d-ae7f-4c93-948c-519589672c30)]
+[scriptable, uuid(d7cdd08e-1bfd-4bc3-9742-d66586781ee2)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -113,26 +113,24 @@ interface nsIDOMDocument : nsIDOMNode
 
   /**
    * Create a range
    *
    * @see http://html5.org/specs/dom-range.html#dom-document-createrange
    */
   nsIDOMRange              createRange();
 
-  nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
-                                        in unsigned long whatToShow,
-                                        in nsIDOMNodeFilter filter,
-                                        in boolean entityReferenceExpansion)
-                                        raises(DOMException);
-  nsIDOMTreeWalker   createTreeWalker(in nsIDOMNode root,
-                                      in unsigned long whatToShow,
-                                      in nsIDOMNodeFilter filter,
-                                      in boolean entityReferenceExpansion)
-                                        raises(DOMException);
+  [optional_argc] nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
+                                                        [optional] in unsigned long whatToShow,
+                                                        [optional] in nsIDOMNodeFilter filter)
+                                                          raises(DOMException);
+  [optional_argc] nsIDOMTreeWalker   createTreeWalker(in nsIDOMNode root,
+                                                      [optional] in unsigned long whatToShow,
+                                                      [optional] in nsIDOMNodeFilter filter)
+                                                        raises(DOMException);
 
   nsIDOMEvent               createEvent(in DOMString eventType)
                                                raises(DOMException);
 
 
   // HTML
   /**
    * The window associated with this document.
deleted file mode 100644
--- a/dom/interfaces/traversal/nsIDOMDocumentTraversal.idl
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is this file as it was released on May 1 2001.
- *
- * The Initial Developer of the Original Code is
- * Jonas Sicking.
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Jonas Sicking <sicking@bigfoot.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "domstubs.idl"
-
-interface nsIDOMNodeIterator;
-interface nsIDOMNodeFilter;
-interface nsIDOMTreeWalker;
-
-
-[scriptable, uuid(13f236c0-47f8-11d5-b6a3-009027446e84)]
-// Introduced in DOM Level 2:
-interface nsIDOMDocumentTraversal : nsISupports
-{
-  nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
-                                        in unsigned long whatToShow,
-                                        in nsIDOMNodeFilter filter,
-                                        in boolean entityReferenceExpansion)
-                                        raises(DOMException);
-  nsIDOMTreeWalker   createTreeWalker(in nsIDOMNode root,
-                                      in unsigned long whatToShow,
-                                      in nsIDOMNodeFilter filter,
-                                      in boolean entityReferenceExpansion)
-                                        raises(DOMException);
-};
--- a/dom/interfaces/traversal/nsIDOMNodeIterator.idl
+++ b/dom/interfaces/traversal/nsIDOMNodeIterator.idl
@@ -39,17 +39,17 @@
 
 #include "domstubs.idl"
 
 interface nsIDOMNodeIterator;
 interface nsIDOMNodeFilter;
 
 
 [scriptable, uuid(5af83f50-c8d5-4824-be29-1aa9d640bacb)]
-// Introduced in DOM Level 2:
+// Introduced in DOM Level 2, updated to DOM Level 4:
 interface nsIDOMNodeIterator : nsISupports
 {
   readonly attribute nsIDOMNode       root;
   readonly attribute unsigned long    whatToShow;
   readonly attribute nsIDOMNodeFilter filter;
   readonly attribute boolean          expandEntityReferences;
   nsIDOMNode         nextNode()
                                         raises(DOMException);
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -795,24 +795,24 @@ ContentChild::GetIndexedDBPath()
     }
 
     return *gIndexedDBPath;
 }
 
 bool
 ContentChild::RecvGarbageCollect()
 {
-    nsJSContext::GarbageCollectNow();
+    nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
     return true;
 }
 
 bool
 ContentChild::RecvCycleCollect()
 {
-    nsJSContext::GarbageCollectNow();
+    nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
     nsJSContext::CycleCollectNow();
     return true;
 }
 
 bool
 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID)
 {
     mAppInfo.version.Assign(version);
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -629,18 +629,16 @@ nsJSONListener::OnStopRequest(nsIRequest
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsJSONListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
                                 nsIInputStream *aStream,
                                 PRUint32 aOffset, PRUint32 aLength)
 {
-  PRUint32 contentLength;
-  aStream->Available(&contentLength);
   nsresult rv = NS_OK;
 
   if (mNeedsConverter && mSniffBuffer.Length() < 4) {
     PRUint32 readCount = (aLength < 4) ? aLength : 4;
     rv = NS_ConsumeStream(aStream, readCount, mSniffBuffer);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (mSniffBuffer.Length() < 4)
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3789,20 +3789,20 @@ WorkerPrivate::UpdateGCZealInternal(JSCo
 
 void
 WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
                                       bool aCollectChildren)
 {
   AssertIsOnWorkerThread();
 
   if (aShrinking) {
-    JS_ShrinkingGC(aCx);
+    js::ShrinkingGC(aCx, js::gcreason::DOM_WORKER);
   }
   else {
-    JS_GC(aCx);
+    js::GCForReason(aCx, js::gcreason::DOM_WORKER);
   }
 
   if (aCollectChildren) {
     for (PRUint32 index = 0; index < mChildWorkers.Length(); index++) {
       mChildWorkers[index]->GarbageCollect(aCx, aShrinking);
     }
   }
 }
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -481,17 +481,17 @@ GetTextNode(nsISelection *selection, nsE
   nsresult res = editor->GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, nsnull);
   if (!editor->IsTextNode(selNode)) {
     // Get an nsINode from the nsIDOMNode
     nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
     // if node is null, return it to indicate there's no text
     NS_ENSURE_TRUE(node, nsnull);
     // This should be the root node, walk the tree looking for text nodes
-    nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull, true);
+    nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull);
     while (!editor->IsTextNode(selNode)) {
       if (NS_FAILED(res = iter.NextNode(getter_AddRefs(selNode))) || !selNode) {
         return nsnull;
       }
     }
   }
   return selNode.forget();
 }
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -33,30 +33,47 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdio.h>
+#include <ctype.h>
 
 #include "jscntxt.h"
 #include "jscrashformat.h"
 #include "jscrashreport.h"
 #include "jsprf.h"
 #include "jsprobes.h"
 #include "jsutil.h"
 #include "prmjtime.h"
 
 #include "gc/Statistics.h"
 
 namespace js {
 namespace gcstats {
 
+static const char *
+ExplainReason(gcreason::Reason reason)
+{
+    switch (reason) {
+#define SWITCH_REASON(name)                     \
+        case gcreason::name:                    \
+          return #name;
+        GCREASONS(SWITCH_REASON)
+
+        default:
+          JS_NOT_REACHED("bad GC reason");
+          return "?";
+#undef SWITCH_REASON
+    }
+}
+
 Statistics::ColumnInfo::ColumnInfo(const char *title, double t, double total)
   : title(title)
 {
     JS_snprintf(str, sizeof(str), "%.1f", t);
     JS_snprintf(totalStr, sizeof(totalStr), "%.1f", total);
     width = 6;
 }
 
@@ -112,18 +129,18 @@ Statistics::makeTable(ColumnInfo *cols)
     cols[i++] = ColumnInfo("-Chu", counts[STAT_DESTROY_CHUNK]);
 
     cols[i++] = ColumnInfo("Reason", ExplainReason(triggerReason));
 
     JS_ASSERT(i == NUM_COLUMNS);
 }
 
 Statistics::Statistics(JSRuntime *rt)
-  : runtime(rt)
-  , triggerReason(PUBLIC_API) //dummy reason to satisfy makeTable
+  : runtime(rt),
+    triggerReason(gcreason::NO_REASON)
 {
     PodArrayZero(counts);
     PodArrayZero(totals);
 
     startupTime = PRMJ_Now();
 
     char *env = getenv("MOZ_GCTIMER");
     if (!env || strcmp(env, "none") == 0) {
@@ -173,17 +190,17 @@ Statistics::~Statistics()
 
 struct GCCrashData
 {
     int isRegen;
     int isCompartment;
 };
 
 void
-Statistics::beginGC(JSCompartment *comp, Reason reason)
+Statistics::beginGC(JSCompartment *comp, gcreason::Reason reason)
 {
     compartment = comp;
 
     PodArrayZero(phaseStarts);
     PodArrayZero(phaseEnds);
     PodArrayZero(phaseTimes);
 
     triggerReason = reason;
@@ -271,17 +288,16 @@ Statistics::endGC()
     crash::SnapshotGCStack();
 
     for (int i = 0; i < PHASE_LIMIT; i++)
         totals[i] += phaseTimes[i];
 
     if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
         (*cb)(JS_TELEMETRY_GC_REASON, triggerReason);
         (*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, compartment ? 1 : 0);
-        (*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN, 0);
         (*cb)(JS_TELEMETRY_GC_MS, t(PHASE_GC));
         (*cb)(JS_TELEMETRY_GC_MARK_MS, t(PHASE_MARK));
         (*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(PHASE_SWEEP));
     }
 
     if (JSGCFinishedCallback cb = runtime->gcFinishedCallback) {
         char buffer[1024];
         statsToString(buffer, sizeof(buffer));
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -37,50 +37,25 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsgc_statistics_h___
 #define jsgc_statistics_h___
 
 #include <string.h>
 
+#include "jsfriendapi.h"
 #include "jspubtd.h"
 #include "jsutil.h"
 
 struct JSCompartment;
 
 namespace js {
 namespace gcstats {
 
-enum Reason {
-    PUBLIC_API,
-    MAYBEGC,
-    LASTCONTEXT,
-    DESTROYCONTEXT,
-    LASTDITCH,
-    TOOMUCHMALLOC,
-    ALLOCTRIGGER,
-    CHUNK,
-    SHAPE,
-    REFILL
-};
-static const int NUM_REASONS = REFILL + 1;
-
-static inline const char *
-ExplainReason(Reason r)
-{
-    static const char *strs[] = {"  API", "Maybe", "LastC", "DestC", "LastD",
-                                 "Mallc", "Alloc", "Chunk", "Shape", "Refil"};
-
-    JS_ASSERT(strcmp(strs[SHAPE], "Shape") == 0 &&
-              sizeof(strs) / sizeof(strs[0]) == NUM_REASONS);
-
-    return strs[r];
-}
-
 enum Phase {
     PHASE_GC,
     PHASE_MARK,
     PHASE_SWEEP,
     PHASE_SWEEP_OBJECT,
     PHASE_SWEEP_STRING,
     PHASE_SWEEP_SCRIPT,
     PHASE_SWEEP_SHAPE,
@@ -98,17 +73,17 @@ enum Stat {
 
     STAT_LIMIT
 };
 
 struct Statistics {
     Statistics(JSRuntime *rt);
     ~Statistics();
 
-    void beginGC(JSCompartment *comp, Reason reason);
+    void beginGC(JSCompartment *comp, gcreason::Reason reason);
     void endGC();
 
     void beginPhase(Phase phase);
     void endPhase(Phase phase);
 
     void count(Stat s) {
         JS_ASSERT(s < STAT_LIMIT);
         counts[s]++;
@@ -117,17 +92,17 @@ struct Statistics {
   private:
     JSRuntime *runtime;
 
     uint64_t startupTime;
 
     FILE *fp;
     bool fullFormat;
 
-    Reason triggerReason;
+    gcreason::Reason triggerReason;
     JSCompartment *compartment;
 
     uint64_t phaseStarts[PHASE_LIMIT];
     uint64_t phaseEnds[PHASE_LIMIT];
     uint64_t phaseTimes[PHASE_LIMIT];
     uint64_t totals[PHASE_LIMIT];
     unsigned int counts[STAT_LIMIT];
 
@@ -135,32 +110,33 @@ struct Statistics {
     double total(Phase phase);
     double beginDelay(Phase phase1, Phase phase2);
     double endDelay(Phase phase1, Phase phase2);
     void printStats();
     void statsToString(char *buffer, size_t size);
 
     struct ColumnInfo {
         const char *title;
-        char str[12];
-        char totalStr[12];
+        char str[32];
+        char totalStr[32];
         int width;
 
         ColumnInfo() {}
         ColumnInfo(const char *title, double t, double total);
         ColumnInfo(const char *title, double t);
         ColumnInfo(const char *title, unsigned int data);
         ColumnInfo(const char *title, const char *data);
     };
 
     void makeTable(ColumnInfo *cols);
 };
 
 struct AutoGC {
-    AutoGC(Statistics &stats, JSCompartment *comp, Reason reason JS_GUARD_OBJECT_NOTIFIER_PARAM)
+    AutoGC(Statistics &stats, JSCompartment *comp, gcreason::Reason reason
+           JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : stats(stats) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginGC(comp, reason); }
     ~AutoGC() { stats.endGC(); }
 
     Statistics &stats;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 struct AutoPhase {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/in.js
@@ -0,0 +1,21 @@
+function f(arr, b) {
+    var res = "";
+    var a;
+    if (b)
+        a = arr;
+    for (var i=100; i>-200; i--) {
+        if (i in a) {
+            res += i;
+        }
+    }
+    return res;
+}
+
+assertEq(f([1, , 2, 3], true), "320");
+
+try {
+    f([1, , 2, 3], false);
+    assertEq(0, 1);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -730,16 +730,17 @@ JSRuntime::JSRuntime()
     gcVerifyData(NULL),
     gcChunkAllocationSinceLastGC(false),
     gcNextFullGCTime(0),
     gcJitReleaseTime(0),
     gcMode(JSGC_MODE_GLOBAL),
     gcIsNeeded(0),
     gcWeakMapList(NULL),
     gcStats(thisFromCtor()),
+    gcTriggerReason(gcreason::NO_REASON),
     gcTriggerCompartment(NULL),
     gcCurrentCompartment(NULL),
     gcCheckCompartment(NULL),
     gcPoke(false),
     gcMarkAndSweep(false),
     gcRunning(false),
 #ifdef JS_GC_ZEAL
     gcZeal_(0),
@@ -2852,17 +2853,17 @@ JS_PUBLIC_API(void)
 JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
 {
     AssertNoGC(cx);
 
     /* We cannot GC the atoms compartment alone; use a full GC instead. */
     JS_ASSERT(comp != cx->runtime->atomsCompartment);
 
     js::gc::VerifyBarriers(cx, true);
-    js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API);
+    js_GC(cx, comp, GC_NORMAL, gcreason::API);
 }
 
 JS_PUBLIC_API(void)
 JS_GC(JSContext *cx)
 {
     JS_CompartmentGC(cx, NULL);
 }
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -318,23 +318,23 @@ js_DestroyContext(JSContext *cx, JSDestr
 
 #ifdef JS_THREADSAFE
         /* Destroying a context implicitly calls JS_EndRequest(). */
         while (cx->outstandingRequests != 0)
             JS_EndRequest(cx);
 #endif
 
         if (last) {
-            js_GC(cx, NULL, GC_NORMAL, gcstats::LASTCONTEXT);
+            js_GC(cx, NULL, GC_NORMAL, gcreason::LAST_CONTEXT);
 
             /* Take the runtime down, now that it has no contexts or atoms. */
             JS_LOCK_GC(rt);
         } else {
             if (mode == JSDCM_FORCE_GC)
-                js_GC(cx, NULL, GC_NORMAL, gcstats::DESTROYCONTEXT);
+                js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT);
             else if (mode == JSDCM_MAYBE_GC)
                 JS_MaybeGC(cx);
 
             JS_LOCK_GC(rt);
         }
     }
 #ifdef JS_THREADSAFE
     rt->gcHelperThread.waitBackgroundSweepEnd();
@@ -1174,17 +1174,17 @@ bool
 JSContext::runningWithTrustedPrincipals() const
 {
     return !compartment || compartment->principals == runtime->trustedPrincipals();
 }
 
 JS_FRIEND_API(void)
 JSRuntime::onTooMuchMalloc()
 {
-    TriggerGC(this, gcstats::TOOMUCHMALLOC);
+    TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
 }
 
 JS_FRIEND_API(void *)
 JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
 {
     /*
      * Retry when we are done with the background sweeping and have stopped
      * all the allocations and released the empty GC chunks.
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -313,17 +313,17 @@ struct JSRuntime
     int64_t             gcJitReleaseTime;
     JSGCMode            gcMode;
     volatile uintptr_t  gcBarrierFailed;
     volatile uintptr_t  gcIsNeeded;
     js::WeakMapBase     *gcWeakMapList;
     js::gcstats::Statistics gcStats;
 
     /* The reason that an interrupt-triggered GC should be called. */
-    js::gcstats::Reason gcTriggerReason;
+    js::gcreason::Reason gcTriggerReason;
 
     /* Pre-allocated space for the GC mark stack. */
     uintptr_t           gcMarkStackArray[js::MARK_STACK_LENGTH];
 
     /*
      * Compartment that triggered GC. If more than one Compatment need GC,
      * gcTriggerCompartment is reset to NULL and a global GC is performed.
      */
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -123,19 +123,25 @@ JS_NewObjectWithUniqueType(JSContext *cx
 {
     JSObject *obj = JS_NewObject(cx, clasp, proto, parent);
     if (!obj || !obj->setSingletonType(cx))
         return NULL;
     return obj;
 }
 
 JS_FRIEND_API(void)
-JS_ShrinkingGC(JSContext *cx)
+js::GCForReason(JSContext *cx, gcreason::Reason reason)
 {
-    js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
+    js_GC(cx, NULL, GC_NORMAL, reason);
+}
+
+JS_FRIEND_API(void)
+js::ShrinkingGC(JSContext *cx, gcreason::Reason reason)
+{
+    js_GC(cx, NULL, GC_SHRINK, reason);
 }
 
 JS_FRIEND_API(void)
 JS_ShrinkGCBuffers(JSRuntime *rt)
 {
     ShrinkGCBuffers(rt);
 }
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -68,19 +68,16 @@ JS_SplicePrototype(JSContext *cx, JSObje
 
 extern JS_FRIEND_API(JSObject *)
 JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(uint32_t)
 JS_ObjectCountDynamicSlots(JSObject *obj);
 
 extern JS_FRIEND_API(void)
-JS_ShrinkingGC(JSContext *cx);
-
-extern JS_FRIEND_API(void)
 JS_ShrinkGCBuffers(JSRuntime *rt);
 
 extern JS_FRIEND_API(size_t)
 JS_GetE4XObjectsCreated(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_SetProtoCalled(JSContext *cx);
 
@@ -96,17 +93,16 @@ JS_NondeterministicGetWeakMapKeys(JSCont
  * process. Uses bounded stack space.
  */
 extern JS_FRIEND_API(void)
 JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape);
 
 enum {
     JS_TELEMETRY_GC_REASON,
     JS_TELEMETRY_GC_IS_COMPARTMENTAL,
-    JS_TELEMETRY_GC_IS_SHAPE_REGEN,
     JS_TELEMETRY_GC_MS,
     JS_TELEMETRY_GC_MARK_MS,
     JS_TELEMETRY_GC_SWEEP_MS
 };
 
 typedef void
 (* JSAccumulateTelemetryDataCallback)(int id, uint32_t sample);
 
@@ -567,16 +563,66 @@ TriggerOperationCallback(JSRuntime *rt);
 class SystemAllocPolicy;
 typedef Vector<JSCompartment*, 0, SystemAllocPolicy> CompartmentVector;
 extern JS_FRIEND_API(const CompartmentVector&)
 GetRuntimeCompartments(JSRuntime *rt);
 
 extern JS_FRIEND_API(size_t)
 SizeOfJSContext();
 
+#define GCREASONS(D)                            \
+    /* Reasons internal to the JS engine */     \
+    D(API)                                      \
+    D(MAYBEGC)                                  \
+    D(LAST_CONTEXT)                             \
+    D(DESTROY_CONTEXT)                          \
+    D(LAST_DITCH)                               \
+    D(TOO_MUCH_MALLOC)                          \
+    D(ALLOC_TRIGGER)                            \
+    D(UNUSED1) /* was CHUNK */                  \
+    D(UNUSED2) /* was SHAPE */                  \
+    D(UNUSED3) /* was REFILL */                 \
+                                                \
+    /* Reasons from Firefox */                  \
+    D(DOM_WINDOW_UTILS)                         \
+    D(COMPONENT_UTILS)                          \
+    D(MEM_PRESSURE)                             \
+    D(CC_WAITING)                               \
+    D(CC_FORCED)                                \
+    D(LOAD_END)                                 \
+    D(POST_COMPARTMENT)                         \
+    D(PAGE_HIDE)                                \
+    D(NSJSCONTEXT_DESTROY)                      \
+    D(SET_NEW_DOCUMENT)                         \
+    D(SET_DOC_SHELL)                            \
+    D(DOM_UTILS)                                \
+    D(DOM_IPC)                                  \
+    D(DOM_WORKER)                               \
+    D(INTER_SLICE_GC)                           \
+    D(REFRESH_FRAME)
+
+namespace gcreason {
+
+/* GCReasons will end up looking like JSGC_MAYBEGC */
+enum Reason {
+#define MAKE_REASON(name) name,
+    GCREASONS(MAKE_REASON)
+#undef MAKE_REASON
+    NO_REASON,
+    NUM_REASONS
+};
+
+} /* namespace gcreason */
+
+extern JS_FRIEND_API(void)
+GCForReason(JSContext *cx, gcreason::Reason reason);
+
+extern JS_FRIEND_API(void)
+ShrinkingGC(JSContext *cx, gcreason::Reason reason);
+
 extern JS_FRIEND_API(bool)
 IsIncrementalBarrierNeeded(JSRuntime *rt);
 
 extern JS_FRIEND_API(bool)
 IsIncrementalBarrierNeeded(JSContext *cx);
 
 extern JS_FRIEND_API(void)
 IncrementalReferenceBarrier(void *ptr);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -737,17 +737,17 @@ Chunk::allocateArena(JSCompartment *comp
     aheader->init(comp, thingKind);
     if (JS_UNLIKELY(!hasAvailableArenas()))
         removeFromAvailableList();
 
     Probes::resizeHeap(comp, rt->gcBytes, rt->gcBytes + ArenaSize);
     rt->gcBytes += ArenaSize;
     comp->gcBytes += ArenaSize;
     if (comp->gcBytes >= comp->gcTriggerBytes)
-        TriggerCompartmentGC(comp, gcstats::ALLOCTRIGGER);
+        TriggerCompartmentGC(comp, gcreason::ALLOC_TRIGGER);
 
     return aheader;
 }
 
 inline void
 Chunk::addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader)
 {
     JS_ASSERT(!aheader->allocated());
@@ -1642,17 +1642,17 @@ ArenaLists::finalizeScripts(JSContext *c
 
 static void
 RunLastDitchGC(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
 
     /* The last ditch GC preserves all atoms. */
     AutoKeepAtoms keep(rt);
-    js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcstats::LASTDITCH);
+    js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcreason::LAST_DITCH);
 }
 
 /* static */ void *
 ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
 {
     JS_ASSERT(cx->compartment->arenas.freeLists[thingKind].isEmpty());
 
     JSCompartment *comp = cx->compartment;
@@ -2132,32 +2132,32 @@ MarkRuntime(JSTracer *trc)
     if (!IS_GC_MARKING_TRACER(trc)) {
         /* We don't want to miss these when called from TraceRuntime. */
         if (JSTraceDataOp op = rt->gcGrayRootsTraceOp)
             (*op)(trc, rt->gcGrayRootsData);
     }
 }
 
 void
-TriggerGC(JSRuntime *rt, gcstats::Reason reason)
+TriggerGC(JSRuntime *rt, gcreason::Reason reason)
 {
     JS_ASSERT(rt->onOwnerThread());
 
     if (rt->gcRunning || rt->gcIsNeeded)
         return;
 
     /* Trigger the GC when it is safe to call an operation callback. */
     rt->gcIsNeeded = true;
     rt->gcTriggerCompartment = NULL;
     rt->gcTriggerReason = reason;
     rt->triggerOperationCallback();
 }
 
 void
-TriggerCompartmentGC(JSCompartment *comp, gcstats::Reason reason)
+TriggerCompartmentGC(JSCompartment *comp, gcreason::Reason reason)
 {
     JSRuntime *rt = comp->rt;
     JS_ASSERT(!rt->gcRunning);
 
     if (rt->gcZeal()) {
         TriggerGC(rt, reason);
         return;
     }
@@ -2193,42 +2193,42 @@ TriggerCompartmentGC(JSCompartment *comp
 
 void
 MaybeGC(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
     JS_ASSERT(rt->onOwnerThread());
 
     if (rt->gcZeal()) {
-        js_GC(cx, NULL, GC_NORMAL, gcstats::MAYBEGC);
+        js_GC(cx, NULL, GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
     JSCompartment *comp = cx->compartment;
     if (rt->gcIsNeeded) {
-        js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
+        js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
     if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) {
-        js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
+        js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
         return;
     }
 
     /*
      * Access to the counters and, on 32 bit, setting gcNextFullGCTime below
      * is not atomic and a race condition could trigger or suppress the GC. We
      * tolerate this.
      */
     int64_t now = PRMJ_Now();
     if (rt->gcNextFullGCTime && rt->gcNextFullGCTime <= now) {
         if (rt->gcChunkAllocationSinceLastGC ||
             rt->gcNumArenasFreeCommitted > FreeCommittedArenasThreshold)
         {
-            js_GC(cx, NULL, GC_SHRINK, gcstats::MAYBEGC);
+            js_GC(cx, NULL, GC_SHRINK, gcreason::MAYBEGC);
         } else {
             rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
         }
     }
 }
 
 static void
 DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp)
@@ -2961,17 +2961,17 @@ GCCycle(JSContext *cx, JSCompartment *co
     rt->setGCLastBytes(rt->gcBytes, gckind);
     rt->gcCurrentCompartment = NULL;
 
     for (CompartmentsIter c(rt); !c.done(); c.next())
         c->setGCLastBytes(c->gcBytes, gckind);
 }
 
 void
-js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Reason reason)
+js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcreason::Reason reason)
 {
     JSRuntime *rt = cx->runtime;
     JS_AbortIfWrongThread(rt);
 
 #ifdef JS_GC_ZEAL
     struct AutoVerifyBarriers {
         JSContext *cx;
         bool inVerify;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1377,21 +1377,21 @@ namespace js {
 extern void
 TraceRuntime(JSTracer *trc);
 
 extern JS_FRIEND_API(void)
 MarkContext(JSTracer *trc, JSContext *acx);
 
 /* Must be called with GC lock taken. */
 extern void
-TriggerGC(JSRuntime *rt, js::gcstats::Reason reason);
+TriggerGC(JSRuntime *rt, js::gcreason::Reason reason);
 
 /* Must be called with GC lock taken. */
 extern void
-TriggerCompartmentGC(JSCompartment *comp, js::gcstats::Reason reason);
+TriggerCompartmentGC(JSCompartment *comp, js::gcreason::Reason reason);
 
 extern void
 MaybeGC(JSContext *cx);
 
 extern void
 ShrinkGCBuffers(JSRuntime *rt);
 
 } /* namespace js */
@@ -1404,17 +1404,17 @@ typedef enum JSGCInvocationKind {
     GC_NORMAL           = 0,
 
     /* Minimize GC triggers and release empty GC chunks right away. */
     GC_SHRINK             = 1
 } JSGCInvocationKind;
 
 /* Pass NULL for |comp| to get a full GC. */
 extern void
-js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcstats::Reason r);
+js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcreason::Reason r);
 
 namespace js {
 
 #ifdef JS_THREADSAFE
 
 class GCHelperThread {
     enum State {
         IDLE,
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -786,16 +786,30 @@ static const JSC::MacroAssembler::Regist
         Address extent(reg, offset);
         if (key.isConstant()) {
             JS_ASSERT(key.index() >= 0);
             return branch32(cond, extent, Imm32(key.index()));
         }
         return branch32(cond, extent, key.reg());
     }
 
+    Jump guardElementNotHole(RegisterID elements, const Int32Key &key) {
+        Jump jmp;
+
+        if (key.isConstant()) {
+            Address slot(elements, key.index() * sizeof(Value));
+            jmp = guardNotHole(slot);
+        } else {
+            BaseIndex slot(elements, key.reg(), JSVAL_SCALE);
+            jmp = guardNotHole(slot);
+        }
+
+        return jmp;
+    }
+
     // Load a jsval from an array slot, given a key. |objReg| is clobbered.
     FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key,
                                      RegisterID typeReg, RegisterID dataReg) {
         JS_ASSERT(objReg != typeReg);
 
         RegisterID elementsReg = objReg;
         loadPtr(Address(objReg, JSObject::offsetOfElements()), elementsReg);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -2961,21 +2961,17 @@ mjit::Compiler::generateMethod()
             prepareStubCall(Uses(1));
             INLINE_STUBCALL(stubs::Throw, REJOIN_NONE);
             frame.pop();
             fallthrough = false;
           END_CASE(JSOP_THROW)
 
           BEGIN_CASE(JSOP_IN)
           {
-            prepareStubCall(Uses(2));
-            INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
-            frame.popn(2);
-            frame.takeReg(Registers::ReturnReg);
-            frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
+            jsop_in();
           }
           END_CASE(JSOP_IN)
 
           BEGIN_CASE(JSOP_INSTANCEOF)
             if (!jsop_instanceof())
                 return Compile_Error;
           END_CASE(JSOP_INSTANCEOF)
 
@@ -7443,16 +7439,86 @@ mjit::Compiler::jsop_toid()
     OOL_STUBCALL(stubs::ToId, REJOIN_FALLTHROUGH);
 
     frame.pop();
     pushSyncedEntry(0);
 
     stubcc.rejoin(Changes(1));
 }
 
+void
+mjit::Compiler::jsop_in()
+{
+    FrameEntry *obj = frame.peek(-1);
+    FrameEntry *id = frame.peek(-2);
+
+    if (cx->typeInferenceEnabled() && id->isType(JSVAL_TYPE_INT32)) {
+        types::TypeSet *types = analysis->poppedTypes(PC, 0);
+
+        if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
+            !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
+            !types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
+        {
+            bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
+
+            if (!obj->isTypeKnown()) {
+                Jump guard = frame.testObject(Assembler::NotEqual, obj);
+                stubcc.linkExit(guard, Uses(2));
+            }
+
+            RegisterID dataReg = frame.copyDataIntoReg(obj);
+
+            Int32Key key = id->isConstant()
+                         ? Int32Key::FromConstant(id->getValue().toInt32())
+                         : Int32Key::FromRegister(frame.tempRegForData(id));
+
+            masm.loadPtr(Address(dataReg, JSObject::offsetOfElements()), dataReg);
+
+            // Guard on the array's initialized length.
+            Jump initlenGuard = masm.guardArrayExtent(ObjectElements::offsetOfInitializedLength(),
+                                                      dataReg, key, Assembler::BelowOrEqual);
+
+            // Guard to make sure we don't have a hole. Skip it if the array is packed.
+            MaybeJump holeCheck;
+            if (!isPacked)
+                holeCheck = masm.guardElementNotHole(dataReg, key);
+
+            masm.move(Imm32(1), dataReg);
+            Jump done = masm.jump();
+
+            Label falseBranch = masm.label();
+            initlenGuard.linkTo(falseBranch, &masm);
+            if (!isPacked)
+                holeCheck.getJump().linkTo(falseBranch, &masm);
+            masm.move(Imm32(0), dataReg);
+
+            done.linkTo(masm.label(), &masm);
+
+            stubcc.leave();
+            OOL_STUBCALL_USES(stubs::In, REJOIN_PUSH_BOOLEAN, Uses(2));
+
+            frame.popn(2);
+            if (dataReg != Registers::ReturnReg)
+                stubcc.masm.move(Registers::ReturnReg, dataReg);
+
+            frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, dataReg);
+
+            stubcc.rejoin(Changes(2));
+
+            return;
+        }
+    }
+
+    prepareStubCall(Uses(2));
+    INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
+    frame.popn(2);
+    frame.takeReg(Registers::ReturnReg);
+    frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
+}
+
 /*
  * For any locals or args which we know to be integers but are treated as
  * doubles by the type inference, convert to double. These will be assumed to be
  * doubles at control flow join points. This function must be called before
  * branching to another opcode.
  *
  * We can only carry entries as doubles when we can track all incoming edges to
  * a join point (no try blocks etc.) and when we can track all writes to the
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -748,16 +748,17 @@ private:
 #endif
     void jsop_toid();
     bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id);
     void jsop_stricteq(JSOp op);
     bool jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     CompileStatus jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused);
     bool jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     void jsop_pos();
+    void jsop_in();
 
     static inline Assembler::Condition
     GetCompareCondition(JSOp op, JSOp fused)
     {
         bool ifeq = fused == JSOP_IFEQ;
         switch (op) {
           case JSOP_GT:
             return ifeq ? Assembler::LessThanOrEqual : Assembler::GreaterThan;
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -385,19 +385,25 @@ interface nsIXPCFunctionThisTranslator :
 /***************************************************************************/
 
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+
+enum nsGCType {
+    nsGCNormal,
+    nsGCShrinking,
+    nsGCIncremental
+};
 %}
 
-[uuid(241e6db3-e018-4d99-b976-c782a05f9c77)]
+[uuid(686bb1d0-4711-11e1-b86c-0800200c9a66)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Initializes classes on a global object that has already been created.
@@ -718,18 +724,20 @@ interface nsIXPConnect : nsISupports
      * from JS into C++. False by default, although any value set in the
      * MOZ_REPORT_ALL_JS_EXCEPTIONS environment variable will override the value
      * passed here.
      */
     void setReportAllJSExceptions(in boolean reportAllJSExceptions);
 
     /**
      * Trigger a JS garbage collection.
+     * Use a js::gcreason::Reason from jsfriendapi.h for the kind.
+     * Use the nsGCType enum for the kind.
      */
-    void GarbageCollect(in boolean shrinkingGC);
+    void GarbageCollect(in PRUint32 reason, in PRUint32 kind);
 
     /**
      * Define quick stubs on the given object, @a proto.
      *
      * @param cx
      *     A context.  Requires request.
      * @param proto
      *     The (newly created) prototype object for a DOM class.  The JS half
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3595,25 +3595,25 @@ nsXPCComponents_Utils::GetWeakReference(
     ref.forget(_retval);
     return NS_OK;
 }
 
 /* void forceGC (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceGC(JSContext *cx)
 {
-    JS_GC(cx);
+    js::GCForReason(cx, js::gcreason::COMPONENT_UTILS);
     return NS_OK;
 }
 
 /* void forceShrinkingGC (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceShrinkingGC(JSContext *cx)
 {
-    JS_ShrinkingGC(cx);
+    js::ShrinkingGC(cx, js::gcreason::COMPONENT_UTILS);
     return NS_OK;
 }
 
 class PreciseGCRunnable : public nsRunnable
 {
   public:
     PreciseGCRunnable(JSContext *aCx, ScheduledGCCallback* aCallback, bool aShrinking)
     : mCallback(aCallback), mCx(aCx), mShrinking(aShrinking) {}
@@ -3631,19 +3631,19 @@ class PreciseGCRunnable : public nsRunna
         JSContext *iter = nsnull;
         while ((cx = JS_ContextIterator(rt, &iter)) != NULL) {
             if (JS_IsRunning(cx)) {
                 return NS_DispatchToMainThread(this);
             }
         }
 
         if (mShrinking)
-            JS_ShrinkingGC(mCx);
+            js::ShrinkingGC(mCx, js::gcreason::COMPONENT_UTILS);
         else
-            JS_GC(mCx);
+            js::GCForReason(mCx, js::gcreason::COMPONENT_UTILS);
 
         mCallback->Callback();
         return NS_OK;
     }
 
   private:
     nsRefPtr<ScheduledGCCallback> mCallback;
     JSContext *mCx;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1865,19 +1865,16 @@ AccumulateTelemetryCallback(int id, uint
 {
     switch (id) {
       case JS_TELEMETRY_GC_REASON:
         Telemetry::Accumulate(Telemetry::GC_REASON, sample);
         break;
       case JS_TELEMETRY_GC_IS_COMPARTMENTAL:
         Telemetry::Accumulate(Telemetry::GC_IS_COMPARTMENTAL, sample);
         break;
-      case JS_TELEMETRY_GC_IS_SHAPE_REGEN:
-        Telemetry::Accumulate(Telemetry::GC_IS_SHAPE_REGEN, sample);
-        break;
       case JS_TELEMETRY_GC_MS:
         Telemetry::Accumulate(Telemetry::GC_MS, sample);
         break;
       case JS_TELEMETRY_GC_MARK_MS:
         Telemetry::Accumulate(Telemetry::GC_MARK_MS, sample);
         break;
       case JS_TELEMETRY_GC_SWEEP_MS:
         Telemetry::Accumulate(Telemetry::GC_SWEEP_MS, sample);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -360,17 +360,17 @@ nsXPConnect::GetInfoForName(const char *
 
 bool
 nsXPConnect::NeedCollect()
 {
     return !!mNeedGCBeforeCC;
 }
 
 void
-nsXPConnect::Collect(bool shrinkingGC)
+nsXPConnect::Collect(PRUint32 reason, PRUint32 kind)
 {
     // We're dividing JS objects into 2 categories:
     //
     // 1. "real" roots, held by the JS engine itself or rooted through the root
     //    and lock JS APIs. Roots from this category are considered black in the
     //    cycle collector, any cycle they participate in is uncollectable.
     //
     // 2. roots held by C++ objects that participate in cycle collection,
@@ -419,26 +419,30 @@ nsXPConnect::Collect(bool shrinkingGC)
     JSContext *cx = ccx.GetJSContext();
 
     // We want to scan the current thread for GC roots only if it was in a
     // request prior to the Collect call to avoid false positives during the
     // cycle collection. So to compensate for JS_BeginRequest in
     // XPCCallContext::Init we disable the conservative scanner if that call
     // has started the request on this thread.
     js::AutoSkipConservativeScan ascs(cx);
-    if (shrinkingGC)
-        JS_ShrinkingGC(cx);
-    else
-        JS_GC(cx);
+    MOZ_ASSERT(reason < js::gcreason::NUM_REASONS);
+    js::gcreason::Reason gcreason = (js::gcreason::Reason)reason;
+    if (kind == nsGCShrinking) {
+        js::ShrinkingGC(cx, gcreason);
+    } else {
+        MOZ_ASSERT(kind == nsGCNormal);
+        js::GCForReason(cx, gcreason);
+    }
 }
 
 NS_IMETHODIMP
-nsXPConnect::GarbageCollect(bool shrinkingGC)
+nsXPConnect::GarbageCollect(PRUint32 reason, PRUint32 kind)
 {
-    Collect(shrinkingGC);
+    Collect(reason, kind);
     return NS_OK;
 }
 
 #ifdef DEBUG_CC
 struct NoteJSRootTracer : public JSTracer
 {
     NoteJSRootTracer(PLDHashTable *aObjects,
                      nsCycleCollectionTraversalCallback& cb)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -544,17 +544,17 @@ public:
     virtual void NotifyLeaveCycleCollectionThread();
     virtual void NotifyEnterMainThread();
     virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
                                           bool explainExpectedLiveGarbage);
     virtual nsresult FinishTraverse();
     virtual nsresult FinishCycleCollection();
     virtual nsCycleCollectionParticipant *ToParticipant(void *p);
     virtual bool NeedCollect();
-    virtual void Collect(bool shrinkingGC=false);
+    virtual void Collect(PRUint32 reason, PRUint32 kind);
 #ifdef DEBUG_CC
     virtual void PrintAllReferencesTo(void *p);
 #endif
 
     XPCCallContext *GetCycleCollectionContext()
     {
         return mCycleCollectionContext;
     }
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -193,16 +193,18 @@ static const char sPrintOptionsContractI
 
 //switch to page layout
 #include "nsGfxCIID.h"
 
 #include "nsObserverService.h"
 
 #include "mozilla/dom/Element.h"
 
+#include "jsfriendapi.h"
+
 using namespace mozilla;
 
 #ifdef NS_DEBUG
 
 #undef NOISY_VIEWER
 #else
 #undef NOISY_VIEWER
 #endif
@@ -1282,17 +1284,17 @@ DocumentViewerImpl::PageHide(bool aIsUnl
   // inform the window so that the focus state is reset.
   NS_ENSURE_STATE(mDocument);
   nsPIDOMWindow *window = mDocument->GetWindow();
   if (window)
     window->PageHidden();
 
   if (aIsUnload) {
     // Poke the GC. The window might be collectable garbage now.
-    nsJSContext::PokeGC();
+    nsJSContext::PokeGC(js::gcreason::PAGE_HIDE);
 
     // if Destroy() was called during OnPageHide(), mDocument is nsnull.
     NS_ENSURE_STATE(mDocument);
 
     // First, get the window from the document...
     nsPIDOMWindow *window = mDocument->GetWindow();
 
     if (!window) {
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -305,17 +305,17 @@ nsContentDLF::CreateInstance(const char*
                           aChannel, aLoadGroup,
                           aContainer, kImageDocumentCID,
                           aDocListener, aDocViewer);
   }
 
   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
   if(pluginHost &&
-     NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType))) {
+     NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType, true))) {
     return CreateDocument(aCommand,
                           aChannel, aLoadGroup,
                           aContainer, kPluginDocumentCID,
                           aDocListener, aDocViewer);
   }
 
   // If we get here, then we weren't able to create anything. Sorry!
   return NS_ERROR_FAILURE;
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -400,16 +400,21 @@ public class AwesomeBar extends Activity
             if (! (menuInfo instanceof ExpandableListView.ExpandableListContextMenuInfo)) {
                 Log.e(LOGTAG, "menuInfo is not ExpandableListContextMenuInfo");
                 return;
             }
             ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
             ExpandableListView exList = (ExpandableListView)list;
             int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
             int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
+
+            // Check if long tap is on a header row
+            if (groupPosition < 0 || childPosition < 0)
+                return;
+
             selectedItem = exList.getExpandableListAdapter().getChild(groupPosition, childPosition);
 
             Map map = (Map)selectedItem;
             title = (String)map.get(URLColumns.TITLE);
         } else {
             if (! (menuInfo instanceof AdapterView.AdapterContextMenuInfo)) {
                 Log.e(LOGTAG, "menuInfo is not AdapterContextMenuInfo");
                 return;
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -47,16 +47,19 @@ include $(topsrcdir)/ipc/app/defs.mk
 DIRS = locales
 
 DIST_FILES = package-name.txt
 
 SYNC_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-sources.mn | tr '\n' ' ';)
 SYNC_PP_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/preprocess-sources.mn | tr '\n' ' ';)
 SYNC_THIRDPARTY_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-third-party-sources.mn | tr '\n' ' ';)
 SYNC_RES_DRAWABLE=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-resources.mn | tr '\n' ' ';)
+SYNC_RES_DRAWABLE_LDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-ldpi-resources.mn | tr '\n' ' ';)
+SYNC_RES_DRAWABLE_MDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-mdpi-resources.mn | tr '\n' ' ';)
+SYNC_RES_DRAWABLE_HDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-hdpi-resources.mn | tr '\n' ' ';)
 SYNC_RES_LAYOUT=$(shell cat $(topsrcdir)/mobile/android/sync/android-layout-resources.mn | tr '\n' ' ';)
 SYNC_RES_VALUES=$(shell cat $(topsrcdir)/mobile/android/sync/android-values-resources.mn | tr '\n' ' ';)
 SYNC_RES_XML=res/xml/sync_authenticator.xml res/xml/sync_options.xml
 SYNC_PP_RES_XML=res/xml/sync_syncadapter.xml
 
 FENNEC_JAVA_FILES = \
   AboutHomeContent.java \
   AlertNotification.java \
@@ -138,17 +141,16 @@ endif
 FENNEC_PP_JAVA_FILES = \
   App.java \
   LauncherShortcuts.java \
   NotificationHandler.java \
   Restarter.java \
   db/BrowserContract.java \
   db/BrowserProvider.java \
   SmsManager.java \
-  SyncPreference.java \
   $(NULL)
 
 
 ifneq (,$(findstring -march=armv7,$(OS_CFLAGS)))
 MIN_CPU_VERSION=7
 else
 MIN_CPU_VERSION=5
 endif
@@ -534,16 +536,19 @@ RESOURCES=$(RES_LAYOUT) $(RES_LAYOUT_V11
 RES_DIRS= \
   res/layout              \
   res/layout-v11          \
   res/values              \
   res/values-v11          \
   res/xml                 \
   res/anim                \
   res/drawable-nodpi      \
+  res/drawable-ldpi       \
+  res/drawable-mdpi       \
+  res/drawable-hdpi       \
   res/drawable-mdpi-v8    \
   res/drawable-hdpi-v8    \
   res/drawable-mdpi-v9    \
   res/drawable-hdpi-v9    \
   res/drawable-mdpi-v11   \
   res/drawable-hdpi-v11   \
   res/drawable-xhdpi-v11  \
   res/drawable-land-mdpi-v14  \
@@ -571,17 +576,20 @@ classes.dex: $(FENNEC_JAVA_FILES) $(FENN
 	$(DX) --dex --output=$@ classes
 
 PP_RES_XML=$(SYNC_PP_RES_XML)
 
 $(PP_RES_XML): $(subst res/,$(srcdir)/resources/, $(PP_RES_XML).in)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
              $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
 
-AndroidManifest.xml $(FENNEC_PP_JAVA_FILES) $(SYNC_PP_JAVA_FILES) package-name.txt: % : %.in Makefile.in
+# AndroidManifest.xml includes these files, so they need to be marked as dependencies.
+SYNC_MANIFEST_FRAGMENTS = $(wildcard $(topsrcdir)/mobile/android/sync/manifests/*.in)
+
+AndroidManifest.xml $(FENNEC_PP_JAVA_FILES) $(SYNC_PP_JAVA_FILES) package-name.txt: % : %.in Makefile.in $(SYNC_MANIFEST_FRAGMENTS)
 	mkdir -p db sync/repositories/android
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
              $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
 
 res/drawable/icon.png: $(MOZ_APP_ICON)
 	$(NSINSTALL) -D res/drawable
 	cp $(ICON_PATH) $@
 
@@ -589,30 +597,45 @@ res/drawable-hdpi/icon.png: $(MOZ_APP_IC
 	$(NSINSTALL) -D res/drawable-hdpi
 	cp $(ICON_PATH_HDPI) $@
 
 RES_DRAWABLE = $(addprefix res/drawable/,$(notdir $(MOZ_ANDROID_DRAWABLES)))
 $(RES_DRAWABLE): $(addprefix $(topsrcdir)/,$(MOZ_ANDROID_DRAWABLES))
 	$(NSINSTALL) -D res/drawable
 	$(NSINSTALL) $^ res/drawable/
 
+RES_DRAWABLE_LDPI = $(addprefix res/drawable-ldpi/,$(notdir $(SYNC_RES_DRAWABLE_LDPI)))
+$(RES_DRAWABLE_LDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_LDPI))
+	$(NSINSTALL) -D res/drawable-ldpi
+	$(NSINSTALL) $^ res/drawable-ldpi/
+
+RES_DRAWABLE_MDPI = $(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI)))
+$(RES_DRAWABLE_MDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_MDPI))
+	$(NSINSTALL) -D res/drawable-mdpi
+	$(NSINSTALL) $^ res/drawable-mdpi/
+
+RES_DRAWABLE_HDPI = $(addprefix res/drawable-hdpi/,$(notdir $(SYNC_RES_DRAWABLE_HDPI)))
+$(RES_DRAWABLE_HDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_HDPI))
+	$(NSINSTALL) -D res/drawable-hdpi
+	$(NSINSTALL) $^ res/drawable-hdpi/
+
 res/values/defaults.xml: $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/res/values/defaults.xml
 	$(NSINSTALL) -D res/values
 	$(NSINSTALL) $^  res/values
 
 $(RES_DIRS):
 	rm -rf $@
 	$(NSINSTALL) -D $@
 
 $(RESOURCES): $(RES_DIRS) $(subst res/,$(srcdir)/resources/,$(RESOURCES))
 	@echo "creating $@"
 	$(NSINSTALL) $(subst res/,$(srcdir)/resources/,$@) $(dir $@)
 
 
-R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
+R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
 
-gecko.ap_: AndroidManifest.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
+gecko.ap_: AndroidManifest.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
 
 libs:: classes.dex package-name.txt
 	$(INSTALL) classes.dex $(FINAL_TARGET)
 	$(INSTALL) package-name.txt $(FINAL_TARGET)
deleted file mode 100644
--- a/mobile/android/base/SyncPreference.java.in
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brian Nicholson <bnicholson@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#filter substitution
-package org.mozilla.gecko;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.preference.Preference;
-import android.util.AttributeSet;
-import android.util.Log;
-
-class SyncPreference extends Preference {
-    private static final String FEEDS_PACKAGE_NAME = "com.android.providers.subscribedfeeds";
-    private static final String ACCOUNT_SYNC_CLASS_NAME = "com.android.settings.AccountSyncSettings";
-    private static final String ACCOUNT_KEY = "account";
-    private static final String FENNEC_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
-    private static final String FENNEC_SYNC_CLASS_NAME = "org.mozilla.gecko.sync.setup.activities.SetupSyncActivity";
-    private static final String FENNEC_ACCOUNT_TYPE = "org.mozilla.firefox_sync";
-
-    private Context mContext;
-
-    public SyncPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mContext = context;
-    }
-
-    @Override
-    protected void onClick() {
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        Account[] accounts = AccountManager.get(mContext).getAccountsByType(FENNEC_ACCOUNT_TYPE);
-        if (accounts.length > 0) {
-            // show sync account
-            // we assume there's exactly one sync account. see bugs 716906 and 710407.
-            intent.setComponent(new ComponentName(FEEDS_PACKAGE_NAME, ACCOUNT_SYNC_CLASS_NAME));
-            Account account = accounts[0];
-            intent.putExtra(ACCOUNT_KEY, account);
-        } else {
-            // show sync setup
-            intent.setComponent(new ComponentName(FENNEC_PACKAGE_NAME, FENNEC_SYNC_CLASS_NAME));
-        }
-        mContext.startActivity(intent);
-    }
-}
--- a/mobile/android/base/db/BrowserProvider.java.in
+++ b/mobile/android/base/db/BrowserProvider.java.in
@@ -177,16 +177,17 @@ public class BrowserProvider extends Con
         map.put(History.DATE_LAST_VISITED, History.DATE_LAST_VISITED);
         map.put(History.DATE_CREATED, History.DATE_CREATED);
         map.put(History.DATE_MODIFIED, History.DATE_MODIFIED);
         map.put(History.GUID, History.GUID);
         map.put(History.IS_DELETED, History.IS_DELETED);
 
         // Images
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "images", IMAGES);
+        URI_MATCHER.addURI(BrowserContract.AUTHORITY, "images/#", IMAGES_ID);
 
         map = IMAGES_PROJECTION_MAP;
         map.put(Images._ID, Images._ID);
         map.put(Images.URL, Images.URL);
         map.put(Images.FAVICON, Images.FAVICON);
         map.put(Images.FAVICON_URL, Images.FAVICON_URL);
         map.put(Images.THUMBNAIL, Images.THUMBNAIL);
         map.put(Images.DATE_CREATED, Images.DATE_CREATED);
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -64,17 +64,16 @@
 <!ENTITY pref_plugins_disabled "Disabled">
 <!ENTITY pref_text_size "Text size">
 <!ENTITY pref_font_size_tiny "Tiny">
 <!ENTITY pref_font_size_small "Small">
 <!ENTITY pref_font_size_medium "Medium">
 <!ENTITY pref_font_size_large "Large">
 <!ENTITY pref_font_size_xlarge "Extra Large">
 <!ENTITY pref_use_master_password "Use master password">
-<!ENTITY pref_sync "Sync">
 
 <!ENTITY quit "Quit">
 
 <!ENTITY addons "Add-ons">
 <!ENTITY downloads "Downloads">
 <!ENTITY char_encoding "Character Encoding">
 
 <!ENTITY share "Share">
--- a/mobile/android/base/locales/en-US/sync_strings.dtd
+++ b/mobile/android/base/locales/en-US/sync_strings.dtd
@@ -1,23 +1,28 @@
 <!-- Don't localize these. They're here until they have
      a better place to live. -->
 <!ENTITY syncBrand.fullName.label "Firefox Sync">
 <!ENTITY syncBrand.shortName.label "Sync">
 
 <!-- Main titles. -->
 <!ENTITY sync.app.name.label '&syncBrand.fullName.label;'>
 <!ENTITY sync.title.connect.label 'Connect to &syncBrand.shortName.label;'>
+<!ENTITY sync.title.adddevice.label 'Add a &syncBrand.fullName.label; Account'>
 <!ENTITY sync.title.pair.label 'Pair a Device'>
 
 <!-- J-PAKE Key Screen -->
 <!ENTITY sync.subtitle.connect.label 'To activate your new device, select “Set up &syncBrand.shortName.label;” on the device.'>
+<!ENTITY sync.subtitle.header.label 'Enter this code on your computer'>
+<!ENTITY sync.subtitle.connectlocation.label 'Select “&sync.title.pair.label;” in the &syncBrand.shortName.label; section of your desktop Firefox options.'>
 <!ENTITY sync.subtitle.pair.label 'To activate, select “Pair a device” on your other device.'>
 <!ENTITY sync.pin.default.label '...\n...\n...\n'>
+<!ENTITY sync.pin.oneline.label '...'>
 <!ENTITY sync.link.show.label 'Show me how.'>
+<!ENTITY sync.link.advancedsetup.label 'Advanced setup...'>
 <!ENTITY sync.link.nodevice.label 'I don\&apos;t have the device with me…'>
 
 <!-- J-PAKE Waiting Screen -->
 <!ENTITY sync.jpake.subtitle.waiting.label 'Waiting for other device…'>
 
 <!-- Account Login Screen -->
 <!ENTITY sync.subtitle.account.label 'Enter your &syncBrand.fullName.label; account information'>
 <!ENTITY sync.input.username.label 'Account Name'>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/pin_background.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+  <solid android:color="#000000" />
+  <stroke android:width="1dp" android:color="#FFFFFF" />
+  <padding
+    android:left="1dp"
+    android:top="1dp"
+    android:right="1dp"
+    android:bottom="1dp" />
+</shape>
\ No newline at end of file
--- a/mobile/android/base/resources/layout/sync_account.xml
+++ b/mobile/android/base/resources/layout/sync_account.xml
@@ -1,28 +1,36 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  style="@style/SyncTextFrame" >
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+  <LinearLayout
+    android:id="@+id/account_top"
+    style="@style/SyncTop">
+
+    <ImageView
+      style="@style/SyncTopIcon" />
+    <TextView
+      style="@style/SyncTextTitle"
+      android:text="@string/sync_title_connect" />
+  </LinearLayout>
 
   <ScrollView
-    style="@style/SyncLayout" >
-    
+    android:id="@+id/account_content"
+    style="@style/SyncLayout"
+    android:layout_below="@id/account_top"
+    android:layout_above="@+id/account_bottom">
+
 	<LinearLayout
-	    style="@style/SyncLayout" >
-	
-	  <TextView
-	    style="@style/SyncTextTitle"
-	    android:text="@string/sync_title_connect" />
-	
-	  <View
-	    style="@style/SyncViewLine" />
-	
+      style="@style/SyncLayout.Vertical"
+      android:padding="20dp" >
+
 	  <TextView
 	    style="@style/SyncTextItem"
-	    android:text="@string/sync_subtitle_account" />
+	    android:text="@string/sync_subtitle_account"
+	    android:layout_marginBottom="10dp" />
 	
 	  <EditText android:id="@+id/usernameInput"
 	    style="@style/SyncEditItem"
 	    android:hint="@string/sync_input_username" />
 	
 	  <EditText android:id="@+id/passwordInput"
 	    style="@style/SyncEditItem"
 	    android:password="true"
@@ -38,31 +46,31 @@
 	    android:layout_gravity="left"
 	    android:imeOptions="actionDone"
 	    android:text="@string/sync_checkbox_server" />
 	
 	  <EditText android:id="@+id/serverInput"
 	    style="@style/SyncEditItem"
 	    android:visibility="gone"
 	    android:hint="@string/sync_input_server" />
-	
-	  <LinearLayout
-	    android:layout_width="fill_parent"
-	    android:layout_height="fill_parent"
-	    android:orientation="horizontal" >
-	
-	    <Button
-	      style="@style/SyncButtonCommon"
-	      android:onClick="cancelClickHandler"
-	      android:text="@string/sync_button_cancel" />
-	
-	    <Button
-	      android:id="@+id/accountConnectButton"
-	      style="@style/SyncButtonCommon"
-	      android:onClick="connectClickHandler"
-	      android:clickable="false"
-	      android:enabled="false"
-	      android:text="@string/sync_button_connect" />
-	
-	  </LinearLayout>
+
 	</LinearLayout>
   </ScrollView>
-</TableLayout>
\ No newline at end of file
+
+  <LinearLayout
+    android:id="@id/account_bottom"
+    style="@style/SyncBottom"
+    android:orientation="horizontal" >
+
+    <Button
+      style="@style/SyncButton"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_cancel" />
+
+    <Button
+      style="@style/SyncButton"
+      android:id="@+id/accountConnectButton"
+      android:onClick="connectClickHandler"
+      android:clickable="false"
+      android:enabled="false"
+      android:text="@string/sync_button_connect" />
+  </LinearLayout>
+</RelativeLayout>
\ No newline at end of file
--- a/mobile/android/base/resources/layout/sync_setup.xml
+++ b/mobile/android/base/resources/layout/sync_setup.xml
@@ -1,65 +1,87 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  style="@style/SyncTextFrame" >
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+
+  <LinearLayout
+    android:id="@+id/setup_top"
+    style="@style/SyncTop" >
+    <ImageView
+      style="@style/SyncTopIcon" />
+    <TextView
+      android:id="@+id/setup_title"
+      style="@style/SyncTextTitle"
+      android:text="@string/sync_title_connect" />
+  </LinearLayout>
 
   <ScrollView
-    style="@style/SyncLayout" >
-
-    <LinearLayout
-      style="@style/SyncLayout" >
+    style="@style/SyncLayout"
+    android:fillViewport="true"
+    android:layout_below="@id/setup_top"
+    android:layout_above="@+id/setup_bottom" >
 
-      <TextView
-          android:id="@+id/setup_title"
-          style="@style/SyncTextTitle"
-          android:text="@string/sync_title_connect" />
-
-      <View
-          android:layout_width="wrap_content"
-          android:layout_height="2dp"
-          android:background="#FFFFFF" />
+    <RelativeLayout
+        style="@style/SyncLayout.Vertical"
+        android:layout_height="fill_parent"
+        android:padding="15dp" >
 
       <TextView
-          android:id="@+id/setup_subtitle"
-          style="@style/SyncTextItem"
-          android:layout_marginTop="10dp"
-          android:layout_marginBottom="10dp"
-          android:text="@string/sync_subtitle_pair" />
+        android:id="@+id/setup_header"
+        style="@style/SyncTextItem"
+        android:gravity="left"
+        android:layout_marginTop="15dp"
+        android:text="@string/sync_subtitle_header"
+        android:textStyle="bold" />
+      <TextView
+        android:id="@+id/setup_subtitle"
+        style="@style/SyncTextItem"
+        android:layout_below="@id/setup_header"
+        android:gravity="left"
+        android:layout_marginTop="2dp"
+        android:text="@string/sync_subtitle_connect" />
 
       <TextView
-          style="@style/SyncLinkItem"
-          android:onClick="showClickHandler"
-          android:text="@string/sync_link_show" />
+        android:id="@+id/setup_showme"
+        style="@style/SyncLinkItem"
+        android:layout_below="@id/setup_subtitle"
+        android:layout_marginTop="2dp"
+        android:onClick="showClickHandler"
+        android:text="@string/sync_link_show" />
 
       <LinearLayout
-          style="@style/SyncTextItem"
-          android:orientation="vertical" >
-
-          <TextView
-              android:id="@+id/text_pin"
-              style="@style/SyncTextItem"
-              android:text="@string/sync_pin_default"
-              android:textSize="40dp" />
+        style="@style/SyncLayout"
+        android:layout_below="@id/setup_showme"
+        android:paddingTop="30dp"
+        android:paddingLeft="-15dp"
+        android:orientation="vertical" >
+        <TextView
+          android:id="@+id/text_pin1"
+          style="@style/SyncPinText" />
+        <TextView
+          android:id="@+id/text_pin2"
+          style="@style/SyncPinText" />
+        <TextView
+          android:id="@+id/text_pin3"
+          style="@style/SyncPinText" />
       </LinearLayout>
 
       <TextView
-          android:id="@+id/link_nodevice"
-          style="@style/SyncLinkItem"
-          android:onClick="manualClickHandler"
-          android:text="@string/sync_link_nodevice" />
-
-      <LinearLayout
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:gravity="center"
-          android:orientation="horizontal" >
-
-          <Button
-              style="@style/SyncButtonCommon"
-              android:layout_marginTop="10dp"
-              android:onClick="cancelClickHandler"
-              android:text="@string/sync_button_cancel" />
-
-      </LinearLayout>
-    </LinearLayout>
+        android:id="@+id/link_nodevice"
+        style="@style/SyncLinkItem"
+        android:layout_alignParentBottom="true"
+        android:gravity="center"
+        android:paddingBottom="5dp"
+        android:onClick="manualClickHandler"
+        android:text="@string/sync_link_advancedsetup" />
+    </RelativeLayout>
   </ScrollView>
-</TableLayout>
+  <LinearLayout
+    android:id="@id/setup_bottom"
+    style="@style/SyncBottom"
+    android:orientation="horizontal" >
+    <Button
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_cancel" />
+  </LinearLayout>
+</RelativeLayout>
\ No newline at end of file
--- a/mobile/android/base/resources/layout/sync_setup_failure.xml
+++ b/mobile/android/base/resources/layout/sync_setup_failure.xml
@@ -1,41 +1,45 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SyncTextFrame" >
-    <TextView
-      style="@style/SyncTextTitle"
-      android:text="@string/sync_title_fail" />
-    <View 
-      style="@style/SyncViewLine" />
-
-    <TextView
-      style="@style/SyncTextItem"
-      android:text="@string/sync_subtitle_fail" />
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" >
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+  <LinearLayout
+    android:id="@+id/failure_top"
+    style="@style/SyncTop" >
+  <ImageView
+    style="@style/SyncTopIcon" />
+  <TextView
+    style="@style/SyncTextTitle"
+    android:text="@string/sync_title_fail" />
+  </LinearLayout>
 
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-
-            <Button
-                style="@style/SyncButtonCommon"
-                android:onClick="tryAgainClickHandler"
-                android:text="@string/sync_button_tryagain" />
+  <TextView
+    style="@style/SyncTextItem"
+    android:layout_below="@id/failure_top"
+    android:layout_above="@+id/failure_bottom"
+    android:padding="20dp"
+    android:text="@string/sync_subtitle_fail" />
+  <LinearLayout
+    android:id="@id/failure_bottom"
+    style="@style/SyncBottom"
+    android:orientation="horizontal" >
 
-            <Button
-                style="@style/SyncButtonCommon"
-                android:onClick="manualClickHandler"
-                android:text="@string/sync_button_manual" />
-        </LinearLayout>
+    <Button
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:layout_weight="1"
+      android:onClick="tryAgainClickHandler"
+      android:text="@string/sync_button_tryagain" />
 
-        <Button
-            style="@style/SyncButtonCommon"
-            android:onClick="cancelClickHandler"
-            android:text="@string/sync_button_cancel" />
-    </LinearLayout>
-
-</TableLayout>
+    <Button
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:layout_weight="1"
+      android:onClick="manualClickHandler"
+      android:text="@string/sync_button_manual" />
+     <Button
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:layout_weight="1"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_cancel" />
+  </LinearLayout>
+</RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_setup_jpake_waiting.xml
+++ b/mobile/android/base/resources/layout/sync_setup_jpake_waiting.xml
@@ -1,23 +1,37 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SyncTextFrame" >
-    <TextView
-        style="@style/SyncTextTitle"
-        android:text="@string/sync_title_connect" />
-    <View
-        style="@style/SyncViewLine" />
-    <ProgressBar
-        style="@android:style/Widget.ProgressBar.Horizontal"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:indeterminateOnly="true"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp" />
-    <TextView
-        style="@style/SyncTextItem"
-        android:text="@string/sync_jpake_subtitle_waiting" />
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+  <LinearLayout
+    android:id="@+id/waiting_top"
+    style="@style/SyncTop" >
+  <ImageView
+    style="@style/SyncTopIcon" />
+  <TextView
+    style="@style/SyncTextTitle"
+    android:text="@string/sync_title_connect" />
+  </LinearLayout>
+
+  <ProgressBar
+    android:id="@+id/waiting_content1"
+    style="@android:style/Widget.ProgressBar.Horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_below="@id/waiting_top"
+    android:indeterminateOnly="true"
+    android:layout_marginTop="40dp"
+    android:layout_marginLeft="15dp"
+    android:layout_marginRight="15dp"
+    android:layout_marginBottom="15dp"/>
+  <TextView
+    style="@style/SyncTextItem"
+    android:gravity="center"
+    android:layout_below="@id/waiting_content1"
+    android:text="@string/sync_jpake_subtitle_waiting" />
+  <LinearLayout
+    style="@style/SyncBottom">
     <Button
-        style="@style/SyncButtonCommon"
-        android:onClick="cancelClickHandler"
-        android:text="@string/sync_button_cancel" />
-</TableLayout>
+      style="@style/SyncButton"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_cancel" />
+  </LinearLayout>
+</RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_setup_nointernet.xml
+++ b/mobile/android/base/resources/layout/sync_setup_nointernet.xml
@@ -1,18 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SyncTextFrame" >
-    <TextView
-        style="@style/SyncTextTitle"
-        android:text="@string/sync_title_fail" />
-    <View
-        style="@style/SyncViewLine"/>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+  <LinearLayout
+    android:id="@+id/internet_top"
+    style="@style/SyncTop">
+    <ImageView
+      style="@style/SyncTopIcon" />
     <TextView
-        style="@style/SyncTextItem"
-        android:text="@string/sync_subtitle_nointernet" />
+      style="@style/SyncTextTitle"
+      android:text="@string/sync_title_fail" />
+  </LinearLayout>
+  <TextView
+    style="@style/SyncTextItem"
+    android:layout_below="@id/internet_top"
+    android:layout_marginTop="20dp"
+    android:gravity="center"
+    android:text="@string/sync_subtitle_nointernet" />
+  <LinearLayout
+    style="@style/SyncBottom" >
     <Button
-        style="@style/SyncButtonCommon"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp"
-        android:onClick="cancelClickHandler"
-        android:text="@string/sync_button_ok" />
-</TableLayout>
\ No newline at end of file
+      style="@style/SyncButton"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_ok" />
+  </LinearLayout>
+</RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_setup_pair.xml
+++ b/mobile/android/base/resources/layout/sync_setup_pair.xml
@@ -1,84 +1,89 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SyncTextFrame" >
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
+  <LinearLayout
+    android:id="@+id/pair_top"
+    style="@style/SyncTop" >
+    <ImageView
+      style="@style/SyncTopIcon" />
+    <TextView
+      android:id="@+id/setup_title"
+      style="@style/SyncTextTitle"
+      android:text="@string/sync_title_pair" />
+  </LinearLayout>
   <ScrollView
-    style="@style/SyncLayout" >
+    style="@style/SyncLayout"
+    android:layout_below="@id/pair_top"
+    android:layout_above="@+id/pair_bottom" >
 
     <LinearLayout
-      style="@style/SyncLayout" >
-
-      <TextView
-        android:id="@+id/setup_title"
-        style="@style/SyncTextTitle"
-        android:text="@string/sync_title_pair" />
-
-      <View
-        style="@style/SyncViewLine" />
+      style="@style/SyncLayout.Vertical"
+      android:gravity="center"
+      android:padding="10dp" >
 
       <TextView
         android:id="@+id/setup_subtitle"
         style="@style/SyncTextItem"
+        android:layout_marginTop="20dp"
         android:layout_marginBottom="10dp"
         android:text="@string/sync_subtitle_connect" />
 
       <TextView
         style="@style/SyncLinkItem"
+        android:layout_marginBottom="10dp"
         android:onClick="showClickHandler"
         android:text="@string/sync_link_show" />
 
       <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="center"
         android:orientation="vertical" >
 
-          <EditText
-            android:id="@+id/pair_row1"
-            style="@style/SyncEditPin" />
-          <EditText
-            android:id="@+id/pair_row2"
-            style="@style/SyncEditPin" />
-          <EditText
-            android:id="@+id/pair_row3"
-            style="@style/SyncEditPin"
-            android:imeOptions="actionDone" />
+        <EditText
+          android:id="@+id/pair_row1"
+          style="@style/SyncEditPin" />
+        <EditText
+          android:id="@+id/pair_row2"
+          style="@style/SyncEditPin" />
+        <EditText
+          android:id="@+id/pair_row3"
+          style="@style/SyncEditPin"
+          android:imeOptions="actionDone" />
       </LinearLayout>
 
       <LinearLayout
         android:id="@+id/pair_error"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="center"
         android:orientation="horizontal"
         android:visibility="invisible" >
 
         <TextView
           style="@style/SyncTextItem"
-          android:layout_marginTop="10dp"
-          android:layout_marginBottom="10dp"
+          android:layout_margin="10dp"
           android:text="@string/sync_pair_tryagain"
           android:textSize="10dp" />
       </LinearLayout>
-
-      <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:orientation="horizontal" >
-
-        <Button
-          style="@style/SyncButtonCommon"
-          android:onClick="cancelClickHandler"
-          android:text="@string/sync_button_cancel" />
-
-        <Button
-          android:id="@+id/pair_button_connect"
-          style="@style/SyncButtonCommon"
-          android:onClick="connectClickHandler"
-          android:clickable="false"
-          android:enabled="false"
-          android:text="@string/sync_button_connect" />
-      </LinearLayout>
     </LinearLayout>
   </ScrollView>
-</TableLayout>
+  <LinearLayout
+    android:id="@id/pair_bottom"
+    style="@style/SyncBottom"
+    android:orientation="horizontal" >
+
+    <Button
+      style="@style/SyncButton"
+      android:onClick="cancelClickHandler"
+      android:text="@string/sync_button_cancel" />
+
+    <Button
+      android:id="@+id/pair_button_connect"
+      style="@style/SyncButton"
+      android:onClick="connectClickHandler"
+      android:clickable="false"
+      android:enabled="false"
+      android:text="@string/sync_button_connect" />
+  </LinearLayout>
+</RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_setup_success.xml
+++ b/mobile/android/base/resources/layout/sync_setup_success.xml
@@ -1,38 +1,29 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SyncTextFrame" >
-
-    <TextView
-        style="@style/SyncTextTitle"
-        android:text="@string/sync_title_success" />
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  style="@style/SyncLayout" >
 
-    <View style="@style/SyncViewLine" />
-
+  <LinearLayout
+    android:id="@+id/success_top"
+    style="@style/SyncTop" >
+    <ImageView
+      style="@style/SyncTopIcon"/>
     <TextView
-        android:id="@+id/setup_success_subtitle"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:padding="20dp"
-        android:text="@string/sync_subtitle_success" />
+      style="@style/SyncTextTitle"
+      android:text="@string/sync_title_success" />
+  </LinearLayout>
+  <TextView
+    android:id="@+id/setup_success_subtitle"
+	style="@style/SyncTextItem"
+	android:gravity="left"
+    android:padding="20dp"
+    android:layout_below="@id/success_top"
+	android:text="@string/sync_subtitle_success" />
 
+  <LinearLayout
+    style="@style/SyncBottom" >
     <Button
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:onClick="settingsClickHandler"
-        android:text="@string/sync_settings" />
-
-    <View
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:layout_weight="1" />
-
-    <TextView
-        android:id="@+id/link_pair"
-        style="@style/SyncLinkItem"
-        android:layout_gravity="center|bottom"
-        android:onClick="pairClickHandler"
-        android:text="@string/sync_title_pair" />
-
-</TableLayout>
\ No newline at end of file
+      style="@style/SyncButton"
+      android:onClick="settingsClickHandler"
+      android:text="@string/sync_settings" />
+  </LinearLayout>
+</RelativeLayout>
\ No newline at end of file
--- a/mobile/android/base/resources/values/sync_styles.xml
+++ b/mobile/android/base/resources/values/sync_styles.xml
@@ -1,59 +1,94 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-  <style name="SyncLayout" parent="@android:style/Widget">
-    <item name="android:layout_width">wrap_content</item>
+  <style name="SyncLayout">
+    <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">fill_parent</item>
-    <item name="android:gravity">center</item>
+  </style>
+  <style name="SyncLayout.Vertical" parent="@style/SyncLayout">
     <item name="android:orientation">vertical</item>
   </style>
+  <style name="SyncLayout.Horizontal" parent="@style/SyncLayout">
+    <item name="android:orientation">horizontal</item>
+  </style>
+
   <!-- TextView Styles -->
   <style name="SyncTextFrame" parent="@android:style/TextAppearance">
-    <item name="android:layout_width">wrap_content</item>
+    <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">fill_parent</item>
     <item name="android:layout_gravity">center</item>
     <item name="android:padding">20dp</item>
     <item name="android:orientation">vertical</item>
-    <item name="android:background">#82818A</item>
   </style>
   <style name="SyncTextItem" parent="@android:style/TextAppearance.Medium">
-    <item name="android:gravity">center</item>
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
-    <item name="android:layout_gravity">center_vertical</item>
     <item name="android:textSize">15dp</item>
   </style>
   <style name="SyncLinkItem" parent="SyncTextItem">
     <item name="android:clickable">true</item>
-    <item name="android:textColor">#99CCFF</item>
+    <item name="android:textColor">#ACC4D5</item>
   </style>
   <style name="SyncTextTitle" parent="@style/SyncTextItem">
-    <item name="android:gravity">center</item>
-    <item name="android:paddingBottom">10dp</item>
+    <item name="android:layout_gravity">center_vertical</item>
+    <item name="android:paddingLeft">4dp</item>
+    <item name="android:gravity">left</item>
     <item name="android:textSize">20dp</item>
   </style>
   <!-- EditView Styles -->
   <style name="SyncEditItem" parent="@android:style/Widget.EditText">
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
     <item name="android:singleLine">true</item>
   </style>
   <style name="SyncEditPin" parent="@style/SyncEditItem">
     <item name="android:layout_width">wrap_content</item>
     <item name="android:gravity">center_horizontal</item>
     <item name="android:ems">4</item>
     <item name="android:maxLength">4</item>
     <item name="android:imeOptions">actionNext</item>
   </style>
-  <!-- Misc Styles -->
-  <style name="SyncButtonCommon">
+
+  <!-- Theme Styles -->
+  <style name="SyncTheme" parent="@android:style/Theme.NoTitleBar"/>
+
+  <style name="SyncTop">
+    <item name="android:layout_width">fill_parent</item>
+    <item name="android:layout_height">wrap_content</item>
+    <item name="android:gravity">left</item>
+    <item name="android:orientation">horizontal</item>
+    <item name="android:layout_alignParentTop">true</item>
+    <item name="android:background">@android:drawable/bottom_bar</item>
+  </style>
+    <style name="SyncBottom">
+    <item name="android:layout_width">fill_parent</item>
+    <item name="android:layout_height">wrap_content</item>
+    <item name="android:gravity">center</item>
+    <item name="android:layout_alignParentBottom">true</item>
+    <item name="android:background">@android:drawable/bottom_bar</item>
+  </style>
+  <style name="SyncButton" parent="@android:style/Widget.Button">
+    <item name="android:layout_width">fill_parent</item>
+    <item name="android:layout_height">wrap_content</item>
+    <item name="android:layout_weight">1</item>
+  </style>
+
+  <!-- Text Display Styles -->
+  <style name="SyncPinText" parent="@android:style/Widget.TextView">
+    <item name="android:layout_width">130sp</item>
+    <item name="android:layout_height">wrap_content</item>
+    <item name="android:layout_gravity">center</item>
+    <item name="android:layout_marginBottom">5dp</item>
+    <item name="android:gravity">center</item>
+    <item name="android:background">@drawable/pin_background</item>
+    <item name="android:textColor">#FFFFFF</item>
+    <item name="android:textSize">35sp</item>
+    <item name="android:text">@string/sync_pin_default</item>
+  </style>
+  <style name="SyncTopIcon">
+    <item name="android:src">@drawable/sync_ic_launcher</item>
     <item name="android:layout_width">wrap_content</item>
     <item name="android:layout_height">wrap_content</item>
-  </style>
-  <style name="SyncViewLine">
-    <item name="android:layout_width">wrap_content</item>
-    <item name="android:layout_height">2dp</item>
-    <item name="android:paddingTop">5dp</item>
-    <item name="android:paddingBottom">10dp</item>
-    <item name="android:background">#FFFFFF</item>
+    <item name="android:paddingTop">2dp</item>
+    <item name="android:paddingLeft">4dp</item>
   </style>
 </resources>
--- a/mobile/android/base/resources/xml/preferences.xml
+++ b/mobile/android/base/resources/xml/preferences.xml
@@ -2,18 +2,19 @@
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                         android:enabled="false">
 
     <PreferenceCategory android:title="@string/pref_category_general">
         <org.mozilla.gecko.LinkPreference android:title="@string/pref_about_firefox"
                                           url="about:" />
 
-        <org.mozilla.gecko.SyncPreference android:title="@string/pref_sync"
-                                          android:persistent="false" />
+        <!-- TODO: Default Search Engine -->
+
+        <!-- TODO: Sync -->
 
     </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/pref_category_content">
 
         <ListPreference     android:key="browser.menu.showCharacterEncoding"
                             android:title="@string/pref_char_encoding"
                             android:entries="@array/pref_char_encoding_entries"
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -69,17 +69,16 @@
   <string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play;</string>
   <string name="pref_plugins_disabled">&pref_plugins_disabled;</string>
   <string name="pref_text_size">&pref_text_size;</string>
   <string name="pref_font_size_tiny">&pref_font_size_tiny;</string>
   <string name="pref_font_size_small">&pref_font_size_small;</string>
   <string name="pref_font_size_medium">&pref_font_size_medium;</string>
   <string name="pref_font_size_large">&pref_font_size_large;</string>
   <string name="pref_font_size_xlarge">&pref_font_size_xlarge;</string>
-  <string name="pref_sync">&pref_sync;</string>
 
   <string name="reload">&reload;</string>
   <string name="forward">&forward;</string>
   <string name="new_tab">&new_tab;</string>
   <string name="addons">&addons;</string>
   <string name="downloads">&downloads;</string>
   <string name="char_encoding">&char_encoding;</string>
 
--- a/mobile/android/base/sync/SyncConfiguration.java
+++ b/mobile/android/base/sync/SyncConfiguration.java
@@ -58,19 +58,19 @@ public class SyncConfiguration implement
     public EditorBranch(SyncConfiguration config, String prefix) {
       if (!prefix.endsWith(".")) {
         throw new IllegalArgumentException("No trailing period in prefix.");
       }
       this.prefix = prefix;
       this.editor = config.getEditor();
     }
 
-    @Override
     public void apply() {
-      this.editor.apply();
+      // Android <=r8 SharedPreferences.Editor does not contain apply() for overriding.
+      this.editor.commit();
     }
 
     @Override
     public Editor clear() {
       this.editor = this.editor.clear();
       return this;
     }
 
--- a/mobile/android/base/sync/Utils.java
+++ b/mobile/android/base/sync/Utils.java
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.sync;
 
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Random;
 
 import org.mozilla.apache.commons.codec.binary.Base32;
 import org.mozilla.apache.commons.codec.binary.Base64;
 import org.mozilla.gecko.sync.crypto.Cryptographer;
 
 import android.content.Context;
@@ -123,18 +122,20 @@ public class Utils {
    * Output: A concatenated version of them
    */
   public static byte[] concatAll(byte[] first, byte[]... rest) {
       int totalLength = first.length;
       for (byte[] array : rest) {
           totalLength += array.length;
       }
   
-      byte[] result = Arrays.copyOf(first, totalLength);
+      byte[] result = new byte[totalLength];
       int offset = first.length;
+
+      System.arraycopy(first, 0, result, 0, offset);
   
       for (byte[] array : rest) {
           System.arraycopy(array, 0, result, offset, array.length);
           offset += array.length;
       }
       return result;
   }
 
--- a/mobile/android/base/sync/crypto/HKDF.java
+++ b/mobile/android/base/sync/crypto/HKDF.java
@@ -35,17 +35,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.sync.crypto;
 
 import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
 
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
 import org.mozilla.gecko.sync.Utils;
 
 
 /*
@@ -93,17 +92,19 @@ public class HKDF {
 
         int iterations = (int) Math.ceil(((double)len) / ((double)BLOCKSIZE));
         for (int i = 0; i < iterations; i++) {
             Tn = digestBytes(Utils.concatAll
                     (Tn, info, Utils.hex2Byte(Integer.toHexString(i + 1))), hmacHasher);
             T = Utils.concatAll(T, Tn);
         }
 
-        return Arrays.copyOfRange(T, 0, len);
+        byte[] result = new byte[len];
+        System.arraycopy(T, 0, result, 0, len);
+        return result;
     }
 
     /*
      * Make HMAC key
      * Input: key (salt)
      * Output: Key HMAC-Key
      */
     public static Key makeHMACKey(byte[] key) {
--- a/mobile/android/base/sync/jpake/JPakeCrypto.java
+++ b/mobile/android/base/sync/jpake/JPakeCrypto.java
@@ -14,17 +14,18 @@
  * The Original Code is Android Sync Client.
  *
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *  Chenxia Liu <liuche@mozilla.com>
+ *   Chenxia Liu <liuche@mozilla.com>
+ *   Richard Newman <rnewman@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -47,59 +48,59 @@ import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
 import org.mozilla.gecko.sync.crypto.HKDF;
 import org.mozilla.gecko.sync.crypto.KeyBundle;
 
 import android.util.Log;
 
 public class JPakeCrypto {
-  private static final String    LOG_TAG = "JpakeCrypto";
+  private static final String LOG_TAG = "JPakeCrypto";
 
   /*
-   * Primes P and Q, and generator G - from original Mozilla jpake
+   * Primes P and Q, and generator G - from original Mozilla J-PAKE
    * implementation.
    */
-  public static final BigInteger P       = new BigInteger(
-                                             "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C"
-                                                 + "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F"
-                                                 + "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1"
-                                                 + "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B"
-                                                 + "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394"
-                                                 + "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0"
-                                                 + "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E"
-                                                 + "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D"
-                                                 + "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F"
-                                                 + "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D"
-                                                 + "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E"
-                                                 + "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73",
-                                             16);
+  public static final BigInteger P = new BigInteger(
+      "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
+      "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
+      "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+      "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
+      "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
+      "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+      "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
+      "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
+      "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+      "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
+      "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
+      "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73",
+      16);
 
-  public static final BigInteger Q       = new BigInteger(
-                                             "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D",
-                                             16);
+  public static final BigInteger Q = new BigInteger(
+      "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D",
+      16);
 
-  public static final BigInteger G       = new BigInteger(
-                                             "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37"
-                                                 + "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB"
-                                                 + "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1"
-                                                 + "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8"
-                                                 + "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17"
-                                                 + "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C"
-                                                 + "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3"
-                                                 + "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B"
-                                                 + "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8"
-                                                 + "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828"
-                                                 + "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33"
-                                                 + "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B",
-                                             16);
+  public static final BigInteger G = new BigInteger(
+      "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
+      "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
+      "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+      "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
+      "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
+      "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+      "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
+      "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
+      "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+      "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
+      "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
+      "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B",
+      16);
 
   /**
    *
-   * Round 1 of JPAKE protocol.
+   * Round 1 of J-PAKE protocol.
    * Generate x1, x2, and ZKP for other party.
    *
    * @param mySignerId
    * @param valuesOut
    */
   public static void round1(JPakeParty jp, JPakeNumGenerator gen) {
     // Randomly select x1 from [0,q), x2 from [1,q).
     BigInteger x1 = gen.generateFromRange(Q); // [0, q)
@@ -113,36 +114,36 @@ public class JPakeCrypto {
     jp.gx2 = gx2;
 
     // Generate and store zero knowledge proofs.
     jp.zkp1 = createZkp(G, x1, gx1, jp.signerId, gen);
     jp.zkp2 = createZkp(G, x2, gx2, jp.signerId, gen);
   }
 
   /**
-   * Round 2 of JPAKE protocol.
+   * Round 2 of J-PAKE protocol.
    * Generate A and ZKP for A.
    * Verify ZKP from other party. Does not check for replay ZKP.
    *
    * @param mySignerId
    * @param valuesOut
    * @param secret
    * @param gx3
    * @param gx4
    * @param zkp3
    * @param zkp4
    * @throws Gx4IsOneException
    * @throws IncorrectZkpException
    */
   public static void round2(String secret, JPakeParty jp,
       JPakeNumGenerator gen) throws Gx4IsOneException, IncorrectZkpException {
 
-    Log.d(LOG_TAG, "round2 started");
+    Log.d(LOG_TAG, "round2 started.");
 
-    if (jp.gx4 == BigInteger.ONE) {
+    if (BigInteger.ONE.compareTo(jp.gx4) == 0) {
       throw new Gx4IsOneException();
     }
 
     // Check ZKP.
     checkZkp(G, jp.gx3, jp.zkp3);
     checkZkp(G, jp.gx4, jp.zkp4);
 
     // Compute a = g^[(x1+x3+x4)*(x2*secret)].
@@ -154,57 +155,56 @@ public class JPakeCrypto {
       // TODO Auto-generated catch block
       e.printStackTrace();
     }
 
     BigInteger a  = y1.modPow(y2, P);
     jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen);
     jp.thisA = a;
 
-    Log.d(LOG_TAG, "round2 finished");
+    Log.d(LOG_TAG, "round2 finished.");
   }
 
   /**
-   * Final round of JPAKE protocol.
+   * Final round of J-PAKE protocol.
    *
    * @param b
    * @param zkp
    * @param secret
    *
    * @return KeyBundle
    * @throws IncorrectZkpException
    */
   public static KeyBundle finalRound(String secret, JPakeParty jp)
       throws IncorrectZkpException {
-    Log.d(LOG_TAG, "final round started");
+    Log.d(LOG_TAG, "Final round started.");
     BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3)
         .mod(P);
     checkZkp(gb, jp.otherA, jp.otherZkpA);
 
     // Calculate shared key g^(x1+x3)*x2*x4*secret, which is equivalent to
     // (B/g^(x2*x4*s))^x2 = (B*(g^x4)^x2^s^-1)^2.
     BigInteger k = jp.gx4.modPow(jp.x2.multiply(new BigInteger(secret.getBytes())).negate().mod(Q), P).multiply(jp.otherA)
         .modPow(jp.x2, P);
 
     byte[] enc = new byte[32];
     byte[] hmac = new byte[32];
     generateKeyAndHmac(k, enc, hmac);
 
-    Log.d(LOG_TAG, "final round finished; returning key");
+    Log.d(LOG_TAG, "Final round finished; returning key.");
     return new KeyBundle(enc, hmac);
   }
 
   // TODO Replace this function with the one in the  crypto library
   private static byte[] HMACSHA256(byte[] data, byte[] key) {
     byte[] result = null;
     try {
       Mac hmacSha256;
       hmacSha256 = Mac.getInstance("HmacSHA256");
-      SecretKeySpec secret_key = new SecretKeySpec(key,
-          "HmacSHA256");
+      SecretKeySpec secret_key = new SecretKeySpec(key, "HmacSHA256");
       hmacSha256.init(secret_key);
       result = hmacSha256.doFinal(data);
     } catch (GeneralSecurityException e) {
       Log.d(LOG_TAG, e.toString());
     }
     return result;
   }
 
@@ -238,38 +238,41 @@ public class JPakeCrypto {
   private static void checkZkp(BigInteger g, BigInteger gx, Zkp zkp)
       throws IncorrectZkpException {
 
     BigInteger h = computeBHash(g, zkp.gr, gx, zkp.id);
 
     // Check parameters of zkp, and compare to computed hash. These shouldn't
     // fail.
     if (gx.compareTo(BigInteger.ZERO) < 1) {// g^x > 1
-      Log.e(LOG_TAG, "g^x > 1 fails");
+      Log.e(LOG_TAG, "g^x > 1 fails.");
+      throw new IncorrectZkpException();
+    }
+    if (gx.compareTo(P.subtract(BigInteger.ONE)) > -1) { // g^x < p-1
+      Log.e(LOG_TAG, "g^x < p-1 fails.");
       throw new IncorrectZkpException();
-    } else if (gx.compareTo(P.subtract(BigInteger.ONE)) > -1) { // g^x < p-1
-      Log.e(LOG_TAG, "g^x < p-1 fails");
+    }
+    if (gx.modPow(Q, P).compareTo(BigInteger.ONE) != 0) {
+      Log.e(LOG_TAG, "g^x^q % p = 1 fails.");
       throw new IncorrectZkpException();
-    } else if (gx.modPow(Q, P).compareTo(BigInteger.ONE) != 0) {
-      Log.e(LOG_TAG, "g^x^q % p = 1 fails");
-    } else if (zkp.gr.compareTo(g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P)) != 0) {
+    }
+    if (zkp.gr.compareTo(g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P)) != 0) {
       // b = r-h*x ==> g^r = g^b*g^x^(h)
       Log.i(LOG_TAG, "gb*g(xh) = "
           + g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P).toString(16));
       Log.d(LOG_TAG, "gr = " + zkp.gr.toString(16));
       Log.d(LOG_TAG, "b = " + zkp.b.toString(16));
       Log.d(LOG_TAG, "g^b = " + g.modPow(zkp.b, P).toString(16));
       Log.d(LOG_TAG, "g^(xh) = " + gx.modPow(h, P).toString(16));
       Log.d(LOG_TAG, "gx = " + gx.toString(16));
       Log.d(LOG_TAG, "h = " + h.toString(16));
-      Log.e(LOG_TAG, "zkp calculation incorrect");
+      Log.e(LOG_TAG, "zkp calculation incorrect.");
       throw new IncorrectZkpException();
-    } else {
-      Log.d(LOG_TAG, "*** ZKP SUCCESS ***");
     }
+    Log.d(LOG_TAG, "*** ZKP SUCCESS ***");
   }
 
   /*
    * Use SHA-256 to compute a BigInteger hash of g, gr, gx values with
    * mySignerId to prevent replay. Does not make a twos-complement BigInteger
    * form hash.
    */
   private static BigInteger computeBHash(BigInteger g, BigInteger gr, BigInteger gx,
--- a/mobile/android/base/sync/net/BaseResource.java
+++ b/mobile/android/base/sync/net/BaseResource.java
@@ -45,16 +45,17 @@ import java.security.NoSuchAlgorithmExce
 import java.security.SecureRandom;
 
 import javax.net.ssl.SSLContext;
 
 import android.util.Log;
 import ch.boye.httpclientandroidlib.Header;
 import ch.boye.httpclientandroidlib.HttpEntity;
 import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpVersion;
 import ch.boye.httpclientandroidlib.auth.Credentials;
 import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 import ch.boye.httpclientandroidlib.client.methods.HttpDelete;
 import ch.boye.httpclientandroidlib.client.methods.HttpGet;
 import ch.boye.httpclientandroidlib.client.methods.HttpPost;
 import ch.boye.httpclientandroidlib.client.methods.HttpPut;
 import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
@@ -152,16 +153,17 @@ public class BaseResource implements Res
     if (credentials != null) {
       BaseResource.applyCredentials(credentials, client, request, context);
     }
 
     HttpParams params = client.getParams();
     HttpConnectionParams.setConnectionTimeout(params, delegate.connectionTimeout());
     HttpConnectionParams.setSoTimeout(params, delegate.socketTimeout());
     HttpProtocolParams.setContentCharset(params, charset);
+    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
     delegate.addHeaders(request, client);
   }
 
   private static Object connManagerMonitor = new Object();
   private static ClientConnectionManager connManager;
 
   /**
    * This method exists for test code.
@@ -177,18 +179,17 @@ public class BaseResource implements Res
 
   public static ClientConnectionManager enableTLSConnectionManager() throws KeyManagementException, NoSuchAlgorithmException  {
     SSLContext sslContext = SSLContext.getInstance("TLS");
     sslContext.init(null, null, new SecureRandom());
     SSLSocketFactory sf = new TLSSocketFactory(sslContext);
     SchemeRegistry schemeRegistry = new SchemeRegistry();
     schemeRegistry.register(new Scheme("https", 443, sf));
     schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory()));
-    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
-        schemeRegistry);
+    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry);
     connManager = cm;
     return cm;
   }
 
   public static ClientConnectionManager getConnectionManager() throws KeyManagementException, NoSuchAlgorithmException
                                                          {
     // TODO: shutdown.
     synchronized (connManagerMonitor) {
--- a/mobile/android/base/sync/net/SyncStorageRequest.java
+++ b/mobile/android/base/sync/net/SyncStorageRequest.java
@@ -168,17 +168,17 @@ public class SyncStorageRequest implemen
       // Clients can use their delegate interface to specify X-Weave-If-Unmodified-Since.
       String ifUnmodifiedSince = this.request.delegate.ifUnmodifiedSince();
       if (ifUnmodifiedSince != null) {
         request.setHeader("x-weave-if-unmodified-since", ifUnmodifiedSince);
       }
     }
   }
 
-  public static String USER_AGENT = "Firefox AndroidSync 0.2";
+  public static String USER_AGENT = "Firefox AndroidSync 0.3";
   protected SyncResourceDelegate resourceDelegate;
   public SyncStorageRequestDelegate delegate;
   protected BaseResource resource;
 
   public SyncStorageRequest() {
     super();
   }
 
--- a/mobile/android/base/sync/net/TLSSocketFactory.java
+++ b/mobile/android/base/sync/net/TLSSocketFactory.java
@@ -38,29 +38,69 @@
 package org.mozilla.gecko.sync.net;
 
 import java.io.IOException;
 import java.net.Socket;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocket;
 
+import android.util.Log;
+
 import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory;
 import ch.boye.httpclientandroidlib.params.HttpParams;
 
 public class TLSSocketFactory extends SSLSocketFactory {
+  private static final String LOG_TAG = "TLSSocketFactory";
+  private static final String[] DEFAULT_CIPHER_SUITES = new String[] {
+    "SSL_RSA_WITH_RC4_128_SHA",        // "RC4_SHA"
+  };
+  private static final String[] DEFAULT_PROTOCOLS = new String[] {
+    "SSLv3",
+    "TLSv1"
+  };
+
+  // Guarded by `this`.
+  private static String[] cipherSuites = DEFAULT_CIPHER_SUITES;
+
   public TLSSocketFactory(SSLContext sslContext) {
     super(sslContext);
   }
 
+  /**
+   * Attempt to specify the cipher suites to use for a connection. If
+   * setting fails (as it will on Android 2.2, because the wrong names
+   * are in use to specify ciphers), attempt to set the defaults.
+   *
+   * We store the list of cipher suites in `cipherSuites`, which
+   * avoids this fallback handling having to be executed more than once.
+   *
+   * This method is synchronized to ensure correct use of that member.
+   *
+   * See Bug 717691 for more details.
+   *
+   * @param socket
+   *        The SSLSocket on which to operate.
+   */
+  public static synchronized void setEnabledCipherSuites(SSLSocket socket) {
+    try {
+      socket.setEnabledCipherSuites(cipherSuites);
+    } catch (IllegalArgumentException e) {
+      cipherSuites = socket.getSupportedCipherSuites();
+      Log.d(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage());
+      Log.d(LOG_TAG, "Using " + cipherSuites.length + " supported suites.");
+      socket.setEnabledCipherSuites(cipherSuites);
+    }
+  }
+
   @Override
   public Socket createSocket(HttpParams params) throws IOException {
     SSLSocket socket = (SSLSocket) super.createSocket(params);
-    socket.setEnabledProtocols(new String[] { "SSLv3", "TLSv1" });
-    socket.setEnabledCipherSuites(new String[] { "SSL_RSA_WITH_RC4_128_SHA" });
+    socket.setEnabledProtocols(DEFAULT_PROTOCOLS);
+    setEnabledCipherSuites(socket);
     return socket;
   }
 
   @Override
   public boolean isSecure(Socket sock) throws IllegalArgumentException {
     return true;
   }
 }
\ No newline at end of file
--- a/mobile/android/base/sync/setup/activities/AccountActivity.java
+++ b/mobile/android/base/sync/setup/activities/AccountActivity.java
@@ -77,16 +77,17 @@ public class AccountActivity extends Acc
   private EditText            usernameInput;
   private EditText            passwordInput;
   private EditText            synckeyInput;
   private CheckBox            serverCheckbox;
   private Button              connectButton;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
+    setTheme(R.style.SyncTheme);
     super.onCreate(savedInstanceState);
     setContentView(R.layout.sync_account);
     mContext = getApplicationContext();
     Log.d(LOG_TAG, "AccountManager.get(" + mContext + ")");
     mAccountManager = AccountManager.get(mContext);
 
     // Find UI elements.
     usernameInput = (EditText) findViewById(R.id.usernameInput);
@@ -127,17 +128,17 @@ public class AccountActivity extends Acc
     // Start with an empty form
     usernameInput.setText("");
     passwordInput.setText("");
     synckeyInput.setText("");
     passwordInput.setText("");
   }
 
   public void cancelClickHandler(View target) {
-    moveTaskToBack(true);
+    finish();
   }
 
   /*
    * Get credentials on "Connect" and write to AccountManager, where it can be
    * accessed by Fennec and Sync Service.
    */
   public void connectClickHandler(View target) {
     Log.d(LOG_TAG, "connectClickHandler for view " + target);
--- a/mobile/android/base/sync/setup/activities/SetupFailureActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupFailureActivity.java
@@ -45,16 +45,17 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 
 public class SetupFailureActivity extends Activity {
   private Context mContext;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
+    setTheme(R.style.SyncTheme);
     super.onCreate(savedInstanceState);
     setContentView(R.layout.sync_setup_failure);
     mContext = this.getApplicationContext();
   }
 
   public void manualClickHandler(View target) {
     Intent intent = new Intent(mContext, AccountActivity.class);
     startActivity(intent);
--- a/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java
@@ -39,41 +39,44 @@ package org.mozilla.gecko.sync.setup.act
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.view.View;
 import android.widget.TextView;
 
 public class SetupSuccessActivity extends Activity {
+  private final static String LOG_TAG = "SetupSuccessActivity";
   private TextView setupSubtitle;
   private Context mContext;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
+    setTheme(R.style.SyncTheme);
     super.onCreate(savedInstanceState);
     mContext = getApplicationContext();
     Bundle extras = this.getIntent().getExtras();
     setContentView(R.layout.sync_setup_success);
     setupSubtitle = ((TextView) findViewById(R.id.setup_success_subtitle));
     if (extras != null) {
       boolean isSetup = extras.getBoolean(Constants.INTENT_EXTRA_IS_SETUP);
       if (!isSetup) {
         setupSubtitle.setText(getString(R.string.sync_subtitle_manage));
       }
     }
   }
 
   /* Click Handlers */
   public void settingsClickHandler(View target) {
-    Intent intent = new Intent("android.settings.SYNC_SETTINGS");
+    Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
     intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
     startActivity(intent);
     finish();
   }
 
   public void pairClickHandler(View target) {
     Intent intent = new Intent(mContext, SetupSyncActivity.class);
     intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
--- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
@@ -48,16 +48,17 @@ import android.accounts.Account;
 import android.accounts.AccountAuthenticatorActivity;
 import android.accounts.AccountManager;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -74,31 +75,34 @@ public class SetupSyncActivity extends A
   private EditText            row3;
   private Button              connectButton;
   private LinearLayout        pinError;
 
   // UI elements for pairing through PIN generation.
   private TextView            setupTitleView;
   private TextView            setupNoDeviceLinkTitleView;
   private TextView            setupSubtitleView;
-  private TextView            pinTextView;
+  private TextView            pinTextView1;
+  private TextView            pinTextView2;
+  private TextView            pinTextView3;
   private JPakeClient         jClient;
 
   // Android context.
   private AccountManager      mAccountManager;
   private Context             mContext;
 
   public SetupSyncActivity() {
     super();
     Log.i(LOG_TAG, "SetupSyncActivity constructor called.");
   }
 
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
+    setTheme(R.style.SyncTheme);
     Log.i(LOG_TAG, "Called SetupSyncActivity.onCreate.");
     super.onCreate(savedInstanceState);
 
     // Set Activity variables.
     mContext = getApplicationContext();
     Log.d(LOG_TAG, "AccountManager.get(" + mContext + ")");
     mAccountManager = AccountManager.get(mContext);
 
@@ -129,19 +133,24 @@ public class SetupSyncActivity extends A
     if (extras != null) {
       boolean isSetup = extras.getBoolean(Constants.INTENT_EXTRA_IS_SETUP);
       if (!isSetup) {
         pairWithPin = true;
         displayPairWithPin();
         return;
       }
     }
-    // Display toast for "Only one account supported."
+    // Display toast for "Only one account supported." and redirect to account management.
     Toast toast = Toast.makeText(mContext, R.string.sync_notification_oneaccount, Toast.LENGTH_LONG);
     toast.show();
+
+    Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+    intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
+    startActivity(intent);
+
     finish();
   }
 
   @Override
   public void onPause() {
     super.onPause();
 
     if (jClient != null) {
@@ -197,30 +206,33 @@ public class SetupSyncActivity extends A
   /* Controller methods */
   public void displayPin(String pin) {
     if (pin == null) {
       Log.w(LOG_TAG, "Asked to display null pin.");
       return;
     }
     // Format PIN for display.
     int charPerLine = pin.length() / 3;
-    String prettyPin = pin.substring(0, charPerLine) + "\n";
-    prettyPin += pin.substring(charPerLine, 2 * charPerLine) + "\n";
-    prettyPin += pin.substring(2 * charPerLine, pin.length());
+    final String pin1 = pin.substring(0, charPerLine);
+    final String pin2 = pin.substring(charPerLine, 2 * charPerLine);
+    final String pin3 = pin.substring(2 * charPerLine, pin.length());
 
-    final String toDisplay = prettyPin;
     runOnUiThread(new Runnable() {
       @Override
       public void run() {
-        TextView view = pinTextView;
-        if (view == null) {
+        TextView view1 = pinTextView1;
+        TextView view2 = pinTextView2;
+        TextView view3 = pinTextView3;
+        if (view1 == null || view2 == null || view3 == null) {
           Log.w(LOG_TAG, "Couldn't find view to display PIN.");
           return;
         }
-        view.setText(toDisplay);
+        view1.setText(pin1);
+        view2.setText(pin2);
+        view3.setText(pin3);
       }
     });
   }
 
   public void displayAbort(String error) {
     if (!Constants.JPAKE_ERROR_USERABORT.equals(error) && !hasInternet()) {
       setContentView(R.layout.sync_setup_nointernet);
       return;
@@ -470,17 +482,19 @@ public class SetupSyncActivity extends A
 
   private void displayReceiveNoPin() {
     setContentView(R.layout.sync_setup);
 
     // Set up UI.
     setupTitleView = ((TextView) findViewById(R.id.setup_title));
     setupSubtitleView = (TextView) findViewById(R.id.setup_subtitle);
     setupNoDeviceLinkTitleView = (TextView) findViewById(R.id.link_nodevice);
-    pinTextView = ((TextView) findViewById(R.id.text_pin));
+    pinTextView1 = ((TextView) findViewById(R.id.text_pin1));
+    pinTextView2 = ((TextView) findViewById(R.id.text_pin2));
+    pinTextView3 = ((TextView) findViewById(R.id.text_pin3));
 
     // UI checks.
     if (setupTitleView == null) {
       Log.e(LOG_TAG, "No title view.");
     }
     if (setupSubtitleView == null) {
       Log.e(LOG_TAG, "No subtitle view.");
     }
--- a/mobile/android/config/mozconfigs/macosx-desktop/nightly
+++ b/mobile/android/config/mozconfigs/macosx-desktop/nightly
@@ -1,15 +1,15 @@
 # Options for client.mk.
 mk_add_options AUTOCONF=autoconf213
 
 # Global options
 . $topsrcdir/build/macosx/mozconfig.leopard
 ac_cv_visibility_pragma=no
 
 ac_add_options --disable-install-strip
-ac_add_options --disable-installer
+
 ac_add_options --enable-application=mobile/android
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 export MOZILLA_OFFICIAL=1
new file mode 100644
--- /dev/null
+++ b/mobile/android/sync/android-drawable-hdpi-resources.mn
@@ -0,0 +1,1 @@
+mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
new file mode 100644
--- /dev/null
+++ b/mobile/android/sync/android-drawable-ldpi-resources.mn
@@ -0,0 +1,1 @@
+mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
new file mode 100644
--- /dev/null
+++ b/mobile/android/sync/android-drawable-mdpi-resources.mn
@@ -0,0 +1,1 @@
+mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
--- a/mobile/android/sync/android-drawable-resources.mn
+++ b/mobile/android/sync/android-drawable-resources.mn
@@ -1,4 +1,2 @@
+mobile/android/base/resources/drawable/pin_background.xml
 mobile/android/base/resources/drawable/sync_icon.png
-mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
-mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
-mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
--- a/mobile/android/sync/strings.xml.in
+++ b/mobile/android/sync/strings.xml.in
@@ -1,18 +1,19 @@
   <string name="sync_app_name">&sync.app.name.label;</string>
-  <string name="sync_title_connect">&sync.title.connect.label;</string>
+  <string name="sync_title_connect">&sync.title.adddevice.label;</string>
   <string name="sync_title_pair">&sync.title.pair.label;</string>
 
   <!-- J-PAKE PIN Screen -->
-  <string name="sync_subtitle_connect">&sync.subtitle.connect.label;</string>
+  <string name="sync_subtitle_header">&sync.subtitle.header.label;</string>
+  <string name="sync_subtitle_connect">&sync.subtitle.connectlocation.label;</string>
   <string name="sync_subtitle_pair">&sync.subtitle.pair.label;</string>
-  <string name="sync_pin_default">&sync.pin.default.label;</string>
-  <string name="sync_link_show">&sync.link.show.label;</string>
-  <string name="sync_link_nodevice">&sync.link.nodevice.label;</string>
+  <string name="sync_pin_default">&sync.pin.oneline.label;</string>
+  <string name="sync_link_show"><u>&sync.link.show.label;</u></string>
+  <string name="sync_link_advancedsetup"><u>&sync.link.advancedsetup.label;</u></string>
 
   <!-- J-PAKE Waiting Screen -->
   
   <string name="sync_jpake_subtitle_waiting">&sync.jpake.subtitle.waiting.label;</string>
 
   <!-- Account Login Screen -->
   <string name="sync_subtitle_account">&sync.subtitle.account.label;</string>
   <string name="sync_input_username">&sync.input.username.label;</string>
--- a/mobile/xul/config/mozconfigs/macosx-desktop/nightly
+++ b/mobile/xul/config/mozconfigs/macosx-desktop/nightly
@@ -1,15 +1,15 @@
 # Options for client.mk.
 mk_add_options AUTOCONF=autoconf213
 
 # Global options
 . $topsrcdir/build/macosx/mozconfig.leopard
 ac_cv_visibility_pragma=no
 
 ac_add_options --disable-install-strip
-ac_add_options --disable-installer
+
 ac_add_options --enable-application=mobile
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 export MOZILLA_OFFICIAL=1
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -581,17 +581,16 @@ nsSocketOutputStream::Write(const char *
     SOCKET_LOG(("  calling PR_Write [count=%u]\n", count));
 
     // cannot hold lock while calling NSPR.  (worried about the fact that PSM
     // synchronously proxies notifications over to the UI thread, which could
     // mistakenly try to re-enter this code.)
     PRInt32 n = PR_Write(fd, buf, count);
 
     SOCKET_LOG(("  PR_Write returned [n=%d]\n", n));
-    NS_ASSERTION(n != 0, "unexpected return value");
 
     nsresult rv;
     {
         MutexAutoLock lock(mTransport->mLock);
 
 #ifdef ENABLE_SOCKET_TRACING
     if (n > 0)
         mTransport->TraceOutBuf(buf, n);
--- a/netwerk/cache/nsCacheEntryDescriptor.cpp
+++ b/netwerk/cache/nsCacheEntryDescriptor.cpp
@@ -910,25 +910,29 @@ nsCompressOutputStreamWrapper::Write(con
 
     // Compress (deflate) the requested buffer. Keep going
     // until the entire buffer has been deflated.
     mZstream.avail_in = count;
     mZstream.next_in = (Bytef*)buf;
     while (mZstream.avail_in > 0) {
         zerr = deflate(&mZstream, Z_NO_FLUSH);
         if (zerr == Z_STREAM_ERROR) {
+            deflateEnd(&mZstream);
+            mStreamInitialized = PR_FALSE;
             return NS_ERROR_FAILURE;
         }
         // Note: Z_BUF_ERROR is non-fatal and sometimes expected here.
 
         // If the compression stream output buffer is filled, write
         // it out to the underlying stream wrapper.
         if (mZstream.avail_out == 0) {
             rv = WriteBuffer();
             if (NS_FAILED(rv)) {
+                deflateEnd(&mZstream);
+                mStreamInitialized = PR_FALSE;
                 return rv;
             }
         }
     }
     *result = count;
     mUncompressedCount += *result;
     return NS_OK;
 }
--- a/netwerk/protocol/http/SpdySession.cpp
+++ b/netwerk/protocol/http/SpdySession.cpp
@@ -846,16 +846,18 @@ SpdySession::HandleSynReply(SpdySession 
     // For the most part we would like to ignore it, but the header needs to be
     // be parsed to keep the compression context synchronized
     self->DownstreamUncompress(self->mFrameBuffer + 14,
                                self->mFrameDataSize - 6);
     self->ChangeDownstreamState(BUFFERING_FRAME_HEADER);
     return NS_OK;
   }
   
+  self->mFrameDataStream->UpdateTransportReadEvents(self->mFrameDataSize);
+
   if (!self->mFrameDataStream->SetFullyOpen()) {
     // "If an endpoint receives multiple SYN_REPLY frames for the same active
     // stream ID, it must drop the stream, and send a RST_STREAM for the
     // stream with the error PROTOCOL_ERROR."
     //
     // In addition to that we abort the session - this is a serious protocol
     // violation.
 
@@ -1123,16 +1125,19 @@ SpdySession::HandleHeaders(SpdySession *
   }
 
   PRUint32 streamID =
     PR_ntohl(reinterpret_cast<PRUint32 *>(self->mFrameBuffer.get())[2]);
 
   // this is actually not legal in the HTTP mapping of SPDY. All
   // headers are in the syn or syn reply. Log and ignore it.
 
+  // in v3 this will be legal and we must remember to note
+  // NS_NET_STATUS_RECEIVING_FROM from it
+
   LOG3(("SpdySession::HandleHeaders %p HEADERS for Stream 0x%X. "
         "They are ignored in the HTTP/SPDY mapping.",
         self, streamID));
   self->ChangeDownstreamState(BUFFERING_FRAME_HEADER);
   return NS_OK;
 }
 
 nsresult
@@ -1143,66 +1148,69 @@ SpdySession::HandleWindowUpdate(SpdySess
   LOG3(("SpdySession::HandleWindowUpdate %p WINDOW UPDATE was "
         "received. WINDOW UPDATE is no longer defined in v2. Ignoring.",
         self));
 
   self->ChangeDownstreamState(BUFFERING_FRAME_HEADER);
   return NS_OK;
 }
 
-// Used for the hashtable enumeration to propogate OnTransportStatus events
-struct transportStatus
-{
-  nsITransport *transport;
-  nsresult status;
-  PRUint64 progress;
-};
-
-static PLDHashOperator
-StreamTransportStatus(nsAHttpTransaction *key,
-                      nsAutoPtr<SpdyStream> &stream,
-                      void *closure)
-{
-  struct transportStatus *status =
-    static_cast<struct transportStatus *>(closure);
-
-  stream->Transaction()->OnTransportStatus(status->transport,
-                                           status->status,
-                                           status->progress);
-  return PL_DHASH_NEXT;
-}
-
-
 //-----------------------------------------------------------------------------
 // nsAHttpTransaction. It is expected that nsHttpConnection is the caller
 // of these methods
 //-----------------------------------------------------------------------------
 
 void
 SpdySession::OnTransportStatus(nsITransport* aTransport,
                                nsresult aStatus,
                                PRUint64 aProgress)
 {
   NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
-  // nsHttpChannel synthesizes progress events in OnDataAvailable
-  if (aStatus == nsISocketTransport::STATUS_RECEIVING_FROM)
-    return;
+  switch (aStatus) {
+    // These should appear only once, deliver to the first
+    // transaction on the session.
+  case NS_NET_STATUS_RESOLVING_HOST:
+  case NS_NET_STATUS_RESOLVED_HOST:
+  case NS_NET_STATUS_CONNECTING_TO:
+  case NS_NET_STATUS_CONNECTED_TO:
+  {
+    SpdyStream *target = mStreamIDHash.Get(1);
+    if (target)
+      target->Transaction()->OnTransportStatus(aTransport, aStatus, aProgress);
+    break;
+  }
 
-  // STATUS_SENDING_TO is handled by SpdyStream
-  if (aStatus == nsISocketTransport::STATUS_SENDING_TO)
-    return;
+  default:
+    // The other transport events are ignored here because there is no good
+    // way to map them to the right transaction in spdy. Instead, the events
+    // are generated again from the spdy code and passed directly to the
+    // correct transaction.
 
-  struct transportStatus status;
-  
-  status.transport = aTransport;
-  status.status = aStatus;
-  status.progress = aProgress;
+    // NS_NET_STATUS_SENDING_TO:
+    // This is generated by the socket transport when (part) of
+    // a transaction is written out
+    //
+    // There is no good way to map it to the right transaction in spdy,
+    // so it is ignored here and generated separately when the SYN_STREAM
+    // is sent from SpdyStream::TransmitFrame
 
-  mStreamTransactionHash.Enumerate(StreamTransportStatus, &status);
+    // NS_NET_STATUS_WAITING_FOR:
+    // Created by nsHttpConnection when the request has been totally sent.
+    // There is no good way to map it to the right transaction in spdy,
+    // so it is ignored here and generated separately when the same
+    // condition is complete in SpdyStream when there is no more
+    // request body left to be transmitted.
+
+    // NS_NET_STATUS_RECEIVING_FROM
+    // Generated in spdysession whenever we read a data frame or a syn_reply
+    // that can be attributed to a particular stream/transaction
+
+    break;
+  }
 }
 
 // ReadSegments() is used to write data to the network. Generally, HTTP
 // request data is pulled from the approriate transaction and
 // converted to SPDY data. Sometimes control data like window-update are
 // generated instead.
 
 nsresult
@@ -1670,16 +1678,17 @@ SpdySession::OnWriteSegment(char *buf,
     rv = mSegmentWriter->OnWriteSegment(buf, count, countWritten);
     if (NS_FAILED(rv))
       return rv;
 
     LogIO(this, mFrameDataStream, "Reading Data Frame", buf, *countWritten);
 
     mFrameDataRead += *countWritten;
     
+    mFrameDataStream->UpdateTransportReadEvents(*countWritten);
     if ((mFrameDataRead == mFrameDataSize) && !mFrameDataLast)
       ChangeDownstreamState(BUFFERING_FRAME_HEADER);
 
     return rv;
   }
   
   if (mDownstreamState == PROCESSING_CONTROL_SYN_REPLY) {
     
--- a/netwerk/protocol/http/SpdyStream.cpp
+++ b/netwerk/protocol/http/SpdyStream.cpp
@@ -70,24 +70,27 @@ SpdyStream::SpdyStream(nsAHttpTransactio
     mStreamID(0),
     mChunkSize(chunkSize),
     mSynFrameComplete(0),
     mBlockedOnWrite(0),
     mRequestBlockedOnRead(0),
     mSentFinOnData(0),
     mRecvdFin(0),
     mFullyOpen(0),
+    mSentWaitingFor(0),
     mTxInlineFrameAllocation(SpdySession::kDefaultBufferSize),
     mTxInlineFrameSize(0),
     mTxInlineFrameSent(0),
     mTxStreamFrameSize(0),
     mTxStreamFrameSent(0),
     mZlib(compressionContext),
     mRequestBodyLen(0),
-    mPriority(priority)
+    mPriority(priority),
+    mTotalSent(0),
+    mTotalRead(0)
 {
   NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
   LOG3(("SpdyStream::SpdyStream %p", this));
 
   mTxInlineFrame = new char[mTxInlineFrameAllocation];
 }
 
@@ -453,16 +456,46 @@ SpdyStream::ParseHttpRequestHeaders(cons
     (mTxInlineFrameSize - 18) * 100 /
     (11 + mTransaction->RequestHead()->RequestURI().Length() +
      mFlatHttpRequestHeaders.Length());
   
   Telemetry::Accumulate(Telemetry::SPDY_SYN_RATIO, ratio);
   return NS_OK;
 }
 
+void
+SpdyStream::UpdateTransportReadEvents(PRUint32 count)
+{
+  mTotalRead += count;
+
+  mTransaction->OnTransportStatus(mSocketTransport,
+                                  NS_NET_STATUS_RECEIVING_FROM,
+                                  mTotalRead);
+}
+
+void
+SpdyStream::UpdateTransportSendEvents(PRUint32 count)
+{
+  mTotalSent += count;
+
+  if (mUpstreamState != SENDING_FIN_STREAM)
+    mTransaction->OnTransportStatus(mSocketTransport,
+                                    NS_NET_STATUS_SENDING_TO,
+                                    mTotalSent);
+
+  if (!mSentWaitingFor && !mRequestBodyLen &&
+      mTxInlineFrameSent == mTxInlineFrameSize  &&
+      mTxStreamFrameSent == mTxStreamFrameSize) {
+    mSentWaitingFor = 1;
+    mTransaction->OnTransportStatus(mSocketTransport,
+                                    NS_NET_STATUS_WAITING_FOR,
+                                    LL_ZERO);
+  }
+}
+
 nsresult
 SpdyStream::TransmitFrame(const char *buf,
                           PRUint32 *countUsed)
 {
   NS_ABORT_IF_FALSE(mTxInlineFrameSize, "empty stream frame in transmit");
   NS_ABORT_IF_FALSE(mSegmentReader, "TransmitFrame with null mSegmentReader");
   
   PRUint32 transmittedCount;
@@ -533,26 +566,21 @@ SpdyStream::TransmitFrame(const char *bu
       mBlockedOnWrite = 1;
 
     if (NS_FAILED(rv))     // this will include WOULD_BLOCK
       return rv;
     
     SpdySession::LogIO(mSession, this, "Writing from Transaction Buffer",
                        buf + offset, transmittedCount);
 
-    if (mUpstreamState == SENDING_REQUEST_BODY) {
-      mTransaction->OnTransportStatus(mSocketTransport,
-                                      nsISocketTransport::STATUS_SENDING_TO,
-                                      transmittedCount);
-    }
-    
     *countUsed += transmittedCount;
     avail -= transmittedCount;
     offset += transmittedCount;
     mTxStreamFrameSent += transmittedCount;
+    UpdateTransportSendEvents(transmittedCount);
   }
 
   if (!avail) {
     mTxInlineFrameSent = 0;
     mTxInlineFrameSize = 0;
     mTxStreamFrameSent = 0;
     mTxStreamFrameSize = 0;
   }
--- a/netwerk/protocol/http/SpdyStream.h
+++ b/netwerk/protocol/http/SpdyStream.h
@@ -84,16 +84,19 @@ public:
     return mTransaction;
   }
 
   void Close(nsresult reason);
 
   void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; }
   bool RecvdFin() { return mRecvdFin; }
 
+  void UpdateTransportSendEvents(PRUint32 count);
+  void UpdateTransportReadEvents(PRUint32 count);
+
   // The zlib header compression dictionary defined by SPDY,
   // and hooks to the mozilla allocator for zlib to use.
   static const char *kDictionary;
   static void *zlib_allocator(void *, uInt, uInt);
   static void zlib_destructor(void *, void *);
 
 private:
 
@@ -166,16 +169,19 @@ private:
 
   // Flag is set after the response frame bearing the fin bit has
   // been processed. (i.e. after the server has closed).
   PRUint32                     mRecvdFin             : 1;
 
   // Flag is set after syn reply received
   PRUint32                     mFullyOpen            : 1;
 
+  // Flag is set after the WAITING_FOR Transport event has been generated
+  PRUint32                     mSentWaitingFor       : 1;
+
   // The InlineFrame and associated data is used for composing control
   // frames and data frame headers.
   nsAutoArrayPtr<char>         mTxInlineFrame;
   PRUint32                     mTxInlineFrameAllocation;
   PRUint32                     mTxInlineFrameSize;
   PRUint32                     mTxInlineFrameSent;
 
   // mTxStreamFrameSize and mTxStreamFrameSent track the progress of
@@ -195,13 +201,16 @@ private:
   // for a stream closed indication. Relying on stream close results
   // in an extra 0-length runt packet and seems to have some interop
   // problems with the google servers.
   PRInt64                      mRequestBodyLen;
 
   // based on nsISupportsPriority definitions
   PRInt32                      mPriority;
 
+  // For Progress Events
+  PRUint64                     mTotalSent;
+  PRUint64                     mTotalRead;
 };
 
 }} // namespace mozilla::net
 
 #endif // mozilla_net_SpdyStream_h
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -70,17 +70,16 @@ HISTOGRAM(CYCLE_COLLECTOR_COLLECTED, 1, 
 HISTOGRAM_BOOLEAN(CYCLE_COLLECTOR_NEED_GC, "Needed garbage collection before cycle collection.")
 HISTOGRAM(CYCLE_COLLECTOR_TIME_BETWEEN, 1, 120, 50, EXPONENTIAL, "Time spent in between cycle collections (seconds)")
 
 /**
  * GC telemetry
  */
 HISTOGRAM(GC_REASON, 1, 20, 20, LINEAR, "Reason (enum value) for initiating a GC")
 HISTOGRAM_BOOLEAN(GC_IS_COMPARTMENTAL, "Is it a compartmental GC?")
-HISTOGRAM_BOOLEAN(GC_IS_SHAPE_REGEN, "Is it a shape regenerating GC?")
 HISTOGRAM(GC_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC (ms)")
 HISTOGRAM(GC_MARK_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC mark phase (ms)")
 HISTOGRAM(GC_SWEEP_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC sweep phase (ms)")
 
 HISTOGRAM(TELEMETRY_PING, 1, 3000, 10, EXPONENTIAL, "Time taken to submit telemetry info (ms)")
 HISTOGRAM_BOOLEAN(TELEMETRY_SUCCESS,  "Successful telemetry submission")
 HISTOGRAM(MEMORY_JS_COMPARTMENTS_SYSTEM, 1, 1000, 50, EXPONENTIAL, "Total JavaScript compartments used for add-ons and internals.")
 HISTOGRAM(MEMORY_JS_COMPARTMENTS_USER, 1, 1000, 50, EXPONENTIAL, "Total JavaScript compartments used for web pages")
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -132,16 +132,52 @@ function getSimpleMeasurements() {
   for (let p in appTimestamps) {
     if (!(p in ret) && appTimestamps[p])
       ret[p] = appTimestamps[p];
   }
 
   return ret;
 }
 
+/**
+ * Read the update channel from defaults only.  We do this to ensure that
+ * the channel is tightly coupled with the application and does not apply
+ * to other installations of the application that may use the same profile.
+ */
+function getUpdateChannel() {
+  var channel = "default";
+  var prefName;
+  var prefValue;
+
+  var defaults = Services.prefs.getDefaultBranch(null);
+  try {
+    channel = defaults.getCharPref("app.update.channel");
+  } catch (e) {
+    // use default when pref not found
+  }
+
+  try {
+    var partners = Services.prefs.getChildList("app.partner.");
+    if (partners.length) {
+      channel += "-cck";
+      partners.sort();
+
+      for each (prefName in partners) {
+        prefValue = Services.prefs.getCharPref(prefName);
+        channel += "-" + prefValue;
+      }
+    }
+  }
+  catch (e) {
+    Cu.reportError(e);
+  }
+
+  return channel;
+}
+
 function TelemetryPing() {}
 
 TelemetryPing.prototype = {
   _histograms: {},
   _initialized: false,
   _prevValues: {},
   // Generate a unique id once per session so the server can cope with
   // duplicate submissions.
@@ -226,17 +262,18 @@ TelemetryPing.prototype = {
     let ai = Services.appinfo;
     let ret = {
       reason: reason,
       OS: ai.OS,
       appID: ai.ID,
       appVersion: ai.version,
       appName: ai.name,
       appBuildID: ai.appBuildID,
-      platformBuildID: ai.platformBuildID,
+      appUpdateChannel: getUpdateChannel(),
+      platformBuildID: ai.platformBuildID
     };
 
     // sysinfo fields are not always available, get what we can.
     let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
     let fields = ["cpucount", "memsize", "arch", "version", "device", "manufacturer", "hardware",
                   "hasMMX", "hasSSE", "hasSSE2", "hasSSE3",
                   "hasSSSE3", "hasSSE4A", "hasSSE4_1", "hasSSE4_2",
                   "hasEDSP", "hasARMv6", "hasNEON"];
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1,9 +1,9 @@
-  /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -209,18 +209,27 @@ static const int kTotalVirtualMemoryPara
 static const char kAvailableVirtualMemoryParameter[] = "AvailableVirtualMemory=";
 static const int kAvailableVirtualMemoryParameterLen =
   sizeof(kAvailableVirtualMemoryParameter)-1;
 
 static const char kOOMAllocationSizeParameter[] = "OOMAllocationSize=";
 static const int kOOMAllocationSizeParameterLen =
   sizeof(kOOMAllocationSizeParameter)-1;
 
+static const char kAvailablePageFileParameter[] = "AvailablePageFile=";
+static const int kAvailablePageFileParameterLen =
+  sizeof(kAvailablePageFileParameter)-1;
+
+static const char kAvailablePhysicalMemoryParameter[] = "AvailablePhysicalMemory=";
+static const int kAvailablePhysicalMemoryParameterLen =
+  sizeof(kAvailablePhysicalMemoryParameter)-1;
+
 // this holds additional data sent via the API
 static Mutex* crashReporterAPILock;
+static Mutex* notesFieldLock;
 static AnnotationTable* crashReporterAPIData_Hash;
 static nsCString* crashReporterAPIData = nsnull;
 static nsCString* notesField = nsnull;
 
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
 #  if defined(XP_WIN) || defined(XP_MACOSX)
@@ -449,44 +458,41 @@ bool MinidumpCallback(const XP_CHAR* dum
       WriteFile(hFile, "\n", 1, &nBytes, NULL);
       if (timeSinceLastCrash != 0) {
         WriteFile(hFile, kTimeSinceLastCrashParameter,
                   kTimeSinceLastCrashParameterLen, &nBytes, NULL);
         WriteFile(hFile, timeSinceLastCrashString, timeSinceLastCrashStringLen,
                   &nBytes, NULL);
         WriteFile(hFile, "\n", 1, &nBytes, NULL);
       }
+
       // Try to get some information about memory.
       MEMORYSTATUSEX statex;
       statex.dwLength = sizeof(statex);
       if (GlobalMemoryStatusEx(&statex)) {
         char buffer[128];
         int bufferLen;
-        WriteFile(hFile, kSysMemoryParameter,
-                  kSysMemoryParameterLen, &nBytes, NULL);
-        ltoa(statex.dwMemoryLoad, buffer, 10);
-        bufferLen = strlen(buffer);
-        WriteFile(hFile, buffer, bufferLen,
-                  &nBytes, NULL);
+
+#define WRITE_STATEX_FIELD(field, paramName, conversionFunc)  \
+        WriteFile(hFile, k##paramName##Parameter,             \
+                  k##paramName##ParameterLen, &nBytes, NULL); \
+        conversionFunc(statex.field, buffer, 10);             \
+        bufferLen = strlen(buffer);                           \
+        WriteFile(hFile, buffer, bufferLen, &nBytes, NULL);   \
         WriteFile(hFile, "\n", 1, &nBytes, NULL);
-        WriteFile(hFile, kTotalVirtualMemoryParameter,
-                  kTotalVirtualMemoryParameterLen, &nBytes, NULL);
-        _ui64toa(statex.ullTotalVirtual, buffer, 10);
-        bufferLen = strlen(buffer);
-        WriteFile(hFile, buffer, bufferLen,
-                  &nBytes, NULL);
-        WriteFile(hFile, "\n", 1, &nBytes, NULL);
-        WriteFile(hFile, kAvailableVirtualMemoryParameter,
-                  kAvailableVirtualMemoryParameterLen, &nBytes, NULL);
-        _ui64toa(statex.ullAvailVirtual, buffer, 10);
-        bufferLen = strlen(buffer);
-        WriteFile(hFile, buffer, bufferLen,
-                  &nBytes, NULL);
-        WriteFile(hFile, "\n", 1, &nBytes, NULL);
+
+        WRITE_STATEX_FIELD(dwMemoryLoad, SysMemory, ltoa);
+        WRITE_STATEX_FIELD(ullTotalVirtual, TotalVirtualMemory, _ui64toa);
+        WRITE_STATEX_FIELD(ullAvailVirtual, AvailableVirtualMemory, _ui64toa);
+        WRITE_STATEX_FIELD(ullAvailPageFile, AvailablePageFile, _ui64toa);
+        WRITE_STATEX_FIELD(ullAvailPhys, AvailablePhysicalMemory, _ui64toa);
+
+#undef WRITE_STATEX_FIELD
       }
+
       if (oomAllocationSizeBufferLen) {
         WriteFile(hFile, kOOMAllocationSizeParameter,
                   kOOMAllocationSizeParameterLen, &nBytes, NULL);
         WriteFile(hFile, oomAllocationSizeBuffer, oomAllocationSizeBufferLen,
                   &nBytes, NULL);
         WriteFile(hFile, "\n", 1, &nBytes, NULL);
       }
       CloseHandle(hFile);
@@ -652,16 +658,18 @@ nsresult SetExceptionHandler(nsILocalFil
   doReport = ShouldReport();
 
   // allocate our strings
   crashReporterAPIData = new nsCString();
   NS_ENSURE_TRUE(crashReporterAPIData, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ASSERTION(!crashReporterAPILock, "Shouldn't have a lock yet");
   crashReporterAPILock = new Mutex("crashReporterAPILock");
+  NS_ASSERTION(!notesFieldLock, "Shouldn't have a lock yet");
+  notesFieldLock = new Mutex("notesFieldLock");
 
   crashReporterAPIData_Hash =
     new nsDataHashtable<nsCStringHashKey,nsCString>();
   NS_ENSURE_TRUE(crashReporterAPIData_Hash, NS_ERROR_OUT_OF_MEMORY);
 
   rv = crashReporterAPIData_Hash->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1081,16 +1089,19 @@ nsresult UnsetExceptionHandler()
   // do this here in the unlikely case that we succeeded in allocating
   // our strings but failed to allocate gExceptionHandler.
   delete crashReporterAPIData_Hash;
   crashReporterAPIData_Hash = nsnull;
 
   delete crashReporterAPILock;
   crashReporterAPILock = nsnull;
 
+  delete notesFieldLock;
+  notesFieldLock = nsnull;
+
   delete crashReporterAPIData;
   crashReporterAPIData = nsnull;
 
   delete notesField;
   notesField = nsnull;
 
   if (crashReporterPath) {
     NS_Free(crashReporterPath);
@@ -1250,16 +1261,20 @@ nsresult AppendAppNotesToCrashReport(con
 {
   if (!GetEnabled())
     return NS_ERROR_NOT_INITIALIZED;
 
   if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
     return NS_ERROR_INVALID_ARG;
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    if (!NS_IsMainThread()) {
+      NS_ERROR("Cannot call AnnotateCrashReport in child processes from non-main thread.");
+      return NS_ERROR_FAILURE;
+    }
     PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
     if (!reporter) {
       EnqueueDelayedNote(new DelayedNote(data));
       return NS_OK;
     }
 
     // Since we don't go through AnnotateCrashReport in the parent process,
     // we must ensure that the data is escaped and valid before the parent
@@ -1269,16 +1284,18 @@ nsresult AppendAppNotesToCrashReport(con
     if (NS_FAILED(rv))
       return rv;
 
     if (!reporter->SendAppendAppNotes(escapedData))
       return NS_ERROR_FAILURE;
     return NS_OK;
   }
 
+  MutexAutoLock lock(*notesFieldLock);
+
   notesField->Append(data);
   return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField);
 }
 
 // Returns true if found, false if not found.
 bool GetAnnotation(const nsACString& key, nsACString& data)
 {
   if (!gExceptionHandler)
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -61,21 +61,22 @@ nsresult SetExceptionHandler(nsILocalFil
 nsresult UnsetExceptionHandler();
 bool     GetEnabled();
 bool     GetServerURL(nsACString& aServerURL);
 nsresult SetServerURL(const nsACString& aServerURL);
 bool     GetMinidumpPath(nsAString& aPath);
 nsresult SetMinidumpPath(const nsAString& aPath);
 
 
-// AnnotateCrashReport may be called from any thread in a chrome process,
-// but may only be called from the main thread in a content process.
+// AnnotateCrashReport and AppendAppNotesToCrashReport may be called from any
+// thread in a chrome process, but may only be called from the main thread in
+// a content process.
 nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
+nsresult AppendAppNotesToCrashReport(const nsACString& data);
 
-nsresult AppendAppNotesToCrashReport(const nsACString& data);
 nsresult SetRestartArgs(int argc, char** argv);
 nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
                         const nsACString& aBuildID);
 
 // Registers an additional memory region to be included in the minidump
 nsresult RegisterAppMemory(void* ptr, size_t length);
 nsresult UnregisterAppMemory(void* ptr);
 
--- a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
@@ -1,32 +1,42 @@
 function run_test()
 {
   if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
     dump("INFO | test_crashreporter.js | Can't test crashreporter in a non-libxul build.\n");
     return;
   }
 
   var is_win7_or_newer = false;
+  var is_windows = false;
   var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"]
              .getService(Components.interfaces.nsIHttpProtocolHandler);
   var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
+  if (match) {
+      is_windows = true;
+  }
   if (match && (parseInt(match[1]) > 6 ||
                 parseInt(match[1]) == 6 && parseInt(match[2]) >= 1)) {
       is_win7_or_newer = true;
   }
 
   // try a basic crash
   do_crash(null, function(mdump, extra) {
              do_check_true(mdump.exists());
              do_check_true(mdump.fileSize > 0);
              do_check_true('StartupTime' in extra);
              do_check_true('CrashTime' in extra);
              do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_THREAD_LIST_STREAM));
              do_check_true(CrashTestUtils.dumpHasInstructionPointerMemory(mdump.path));
+             if (is_windows) {
+               ['SystemMemoryUsePercentage', 'TotalVirtualMemory', 'AvailableVirtualMemory',
+                'AvailablePageFile', 'AvailablePhysicalMemory'].forEach(function(prop) {
+                  do_check_true(extra[prop].toString().match(/^\d+$/));
+               });
+             }
              if (is_win7_or_newer)
                do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM));
            });
 
   // check setting some basic data
   do_crash(function() {
              crashReporter.annotateCrashReport("TestKey", "TestValue");
              crashReporter.appendAppNotesToCrashReport("Junk");
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -420,16 +420,17 @@ OS_LIBS += -lGLESv2
 endif
 
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 OS_LIBS += \
   -lui \
   -lmedia \
   -lhardware_legacy \
   -lhardware \
+  -lutils \
   $(NULL)
 endif
 
 EXTRA_DEPS += \
   $(topsrcdir)/intl/unicharutil/util/objs.mk \
   $(topsrcdir)/rdf/util/src/objs.mk \
   $(NULL)
 
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -37,67 +37,51 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #define _GNU_SOURCE
 
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/input.h>
 #include <signal.h>
 #include <sys/epoll.h>
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "nscore.h"
 #include "mozilla/FileUtils.h"
+#include "mozilla/Mutex.h"
 #include "mozilla/Services.h"
 #include "nsAppShell.h"
 #include "nsGkAtoms.h"
 #include "nsGUIEvent.h"
 #include "nsIObserverService.h"
 #include "nsWindow.h"
 
 #include "android/log.h"
-
-#ifndef ABS_MT_TOUCH_MAJOR
-// Taken from include/linux/input.h
-// XXX update the bionic input.h so we don't have to do this!
-#define ABS_X			0x00
-#define ABS_Y			0x01
-// ...
-#define ABS_MT_TOUCH_MAJOR      0x30    /* Major axis of touching ellipse */
-#define ABS_MT_TOUCH_MINOR      0x31    /* Minor axis (omit if circular) */
-#define ABS_MT_WIDTH_MAJOR      0x32    /* Major axis of approaching ellipse */
-#define ABS_MT_WIDTH_MINOR      0x33    /* Minor axis (omit if circular) */
-#define ABS_MT_ORIENTATION      0x34    /* Ellipse orientation */
-#define ABS_MT_POSITION_X       0x35    /* Center X ellipse position */
-#define ABS_MT_POSITION_Y       0x36    /* Center Y ellipse position */
-#define ABS_MT_TOOL_TYPE        0x37    /* Type of touching device */
-#define ABS_MT_BLOB_ID          0x38    /* Group a set of packets as a blob */
-#define ABS_MT_TRACKING_ID      0x39    /* Unique ID of initiated contact */
-#define ABS_MT_PRESSURE         0x3a    /* Pressure on contact area */
-#define SYN_MT_REPORT           2
-#endif
+#include "ui/EventHub.h"
+#include "ui/InputReader.h"
+#include "ui/InputDispatcher.h"
 
 #define LOG(args...)                                            \
     __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #ifdef VERBOSE_LOG_ENABLED
 # define VERBOSE_LOG(args...)                           \
     __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #else
 # define VERBOSE_LOG(args...)                   \
     (void)0
 #endif
 
 using namespace mozilla;
+using namespace android;
 
 bool gDrawRequest = false;
 static nsAppShell *gAppShell = NULL;
 static int epollfd = 0;
 static int signalfds[2] = {0};
 
 namespace mozilla {
 
@@ -118,139 +102,237 @@ pipeHandler(int fd, FdHandler *data)
 {
     ssize_t len;
     do {
         char tmp[32];
         len = read(fd, tmp, sizeof(tmp));
     } while (len > 0);
 }
 
-static
-PRUint64 timevalToMS(const struct timeval &time)
-{
-    return time.tv_sec * 1000 + time.tv_usec / 1000;
-}
-
 static void
-sendMouseEvent(PRUint32 msg, struct timeval& time, int x, int y)
+sendMouseEvent(PRUint32 msg, uint64_t timeMs, int x, int y)
 {
     nsMouseEvent event(true, msg, NULL,
                        nsMouseEvent::eReal, nsMouseEvent::eNormal);
 
     event.refPoint.x = x;
     event.refPoint.y = y;
-    event.time = timevalToMS(time);
+    event.time = timeMs;
     event.isShift = false;
     event.isControl = false;
     event.isMeta = false;
     event.isAlt = false;
     event.button = nsMouseEvent::eLeftButton;
     if (msg != NS_MOUSE_MOVE)
         event.clickCount = 1;
 
     nsWindow::DispatchInputEvent(event);
 }
 
 static nsEventStatus
 sendKeyEventWithMsg(PRUint32 keyCode,
                     PRUint32 msg,
-                    const timeval &time,
+                    uint64_t timeMs,
                     PRUint32 flags)
 {
     nsKeyEvent event(true, msg, NULL);
     event.keyCode = keyCode;
-    event.time = timevalToMS(time);
+    event.time = timeMs;
     event.flags |= flags;
     return nsWindow::DispatchInputEvent(event);
 }
 
 static void
-sendKeyEvent(PRUint32 keyCode, bool down, const timeval &time)
+sendKeyEvent(PRUint32 keyCode, bool down, uint64_t timeMs)
 {
     nsEventStatus status =
-        sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, time, 0);
+        sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, timeMs, 0);
     if (down) {
-        sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, time,
+        sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, timeMs,
                             status == nsEventStatus_eConsumeNoDefault ?
                             NS_EVENT_FLAG_NO_DEFAULT : 0);
     }
 }
 
 static void
-sendSpecialKeyEvent(nsIAtom *command, const timeval &time)
+sendSpecialKeyEvent(nsIAtom *command, uint64_t timeMs)
 {
     nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, NULL);
-    event.time = timevalToMS(time);
+    event.time = timeMs;
     nsWindow::DispatchInputEvent(event);
 }
 
 static void
-maybeSendKeyEvent(int keyCode, bool pressed, const timeval& time)
+maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs)
 {
     switch (keyCode) {
     case KEY_BACK:
-        sendKeyEvent(NS_VK_ESCAPE, pressed, time);
+        sendKeyEvent(NS_VK_ESCAPE, pressed, timeMs);
         break;
     case KEY_MENU:
         if (!pressed)
-            sendSpecialKeyEvent(nsGkAtoms::Menu, time);
+            sendSpecialKeyEvent(nsGkAtoms::Menu, timeMs);
         break;
     case KEY_SEARCH:
         if (pressed)
-            sendSpecialKeyEvent(nsGkAtoms::Search, time);
+            sendSpecialKeyEvent(nsGkAtoms::Search, timeMs);
         break;
     case KEY_HOME:
-        sendKeyEvent(NS_VK_HOME, pressed, time);
+        sendKeyEvent(NS_VK_HOME, pressed, timeMs);
         break;
     case KEY_POWER:
-        sendKeyEvent(NS_VK_SLEEP, pressed, time);
+        sendKeyEvent(NS_VK_SLEEP, pressed, timeMs);
         break;
     case KEY_VOLUMEUP:
         if (pressed)
-            sendSpecialKeyEvent(nsGkAtoms::VolumeUp, time);
+            sendSpecialKeyEvent(nsGkAtoms::VolumeUp, timeMs);
         break;
     case KEY_VOLUMEDOWN:
         if (pressed)
-            sendSpecialKeyEvent(nsGkAtoms::VolumeDown, time);
+            sendSpecialKeyEvent(nsGkAtoms::VolumeDown, timeMs);
         break;
     default:
         VERBOSE_LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d",
                     keyCode, pressed);
     }
 }
 
-static void
-maybeSendKeyEvent(const input_event& e)
-{
-    if (e.type != EV_KEY) {
-        VERBOSE_LOG("Got unknown key event type. type 0x%04x code 0x%04x value %d",
-            e.type, e.code, e.value);
-        return;
-    }
+struct UserInputData {
+    uint64_t timeMs;
+    enum {
+        MOTION_DATA,
+        KEY_DATA
+    } type;
+    int32_t action;
+    int32_t flags;
+    int32_t metaState;
+    union {
+        struct {
+            int32_t keyCode;
+            int32_t scanCode;
+        } key;
+        struct {
+            PointerCoords coords;
+        } motion;
+    };
+};
+
+class GeckoInputReaderPolicy : public InputReaderPolicyInterface {
+public:
+    GeckoInputReaderPolicy() {}
+
+    virtual bool getDisplayInfo(int32_t displayId,
+            int32_t* width, int32_t* height, int32_t* orientation);
+    virtual bool filterTouchEvents();
+    virtual bool filterJumpyTouchEvents();
+    virtual nsecs_t getVirtualKeyQuietTime();
+    virtual void getVirtualKeyDefinitions(const String8& deviceName,
+            Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
+    virtual void getInputDeviceCalibration(const String8& deviceName,
+            InputDeviceCalibration& outCalibration);
+    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
+
+protected:
+    virtual ~GeckoInputReaderPolicy() {}
+};
+
+class GeckoInputDispatcher : public InputDispatcherInterface {
+public:
+    GeckoInputDispatcher()
+        : mQueueLock("GeckoInputDispatcher::mQueueMutex")
+    {}
+
+    virtual void dump(String8& dump);
+
+    // Called on the main thread
+    virtual void dispatchOnce();
 
-    if (e.value != 0 && e.value != 1) {
-        VERBOSE_LOG("Got unknown key event value. type 0x%04x code 0x%04x value %d",
-            e.type, e.code, e.value);
-        return;
-    }
+    // notify* methods are called on the InputReaderThread
+    virtual void notifyConfigurationChanged(nsecs_t eventTime);
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+            int32_t scanCode, int32_t metaState, nsecs_t downTime);
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
+            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+            float xPrecision, float yPrecision, nsecs_t downTime);
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags);
+
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
+    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
+    virtual void setFocusedApplication(const InputApplication* inputApplication);
+    virtual void setInputDispatchMode(bool enabled, bool frozen);
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+protected:
+    virtual ~GeckoInputDispatcher() {}
 
-    bool pressed = e.value == 1;
-    maybeSendKeyEvent(e.code, pressed, e.time);
+private:
+    // mQueueLock should generally be locked while using mEventQueue.
+    // UserInputData is pushed on on the InputReaderThread and
+    // popped and dispatched on the main thread.
+    mozilla::Mutex mQueueLock;
+    std::queue<UserInputData> mEventQueue;
+};
+
+// GeckoInputReaderPolicy
+bool
+GeckoInputReaderPolicy::getDisplayInfo(int32_t displayId,
+                                       int32_t* width,
+                                       int32_t* height,
+                                       int32_t* orientation)
+{
+    // 0 is the default displayId. We only support one display
+    if (displayId)
+        return false;
+
+    if (width)
+        *width = gScreenBounds.width;
+    if (height)
+        *height = gScreenBounds.height;
+    if (orientation)
+        *orientation = ROTATION_0;
+    return true;
 }
 
-static void
-configureVButtons(FdHandler& data)
+bool
+GeckoInputReaderPolicy::filterTouchEvents()
+{
+    return false;
+}
+
+bool
+GeckoInputReaderPolicy::filterJumpyTouchEvents()
 {
+    return false;
+}
+
+nsecs_t
+GeckoInputReaderPolicy::getVirtualKeyQuietTime()
+{
+    return 0;
+}
+
+void
+GeckoInputReaderPolicy::getVirtualKeyDefinitions(const String8& deviceName,
+    Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions)
+{
+    outVirtualKeyDefinitions.clear();
+
     char vbuttonsPath[PATH_MAX];
     snprintf(vbuttonsPath, sizeof(vbuttonsPath),
              "/sys/board_properties/virtualkeys.%s",
-             data.name);
+             deviceName.string());
     ScopedClose fd(open(vbuttonsPath, O_RDONLY));
     if (0 > fd.mFd) {
-        LOG("No vbuttons for mt device %s", data.name);
+        LOG("No vbuttons for mt device %s", deviceName.string());
         return;
     }
 
     // This device has vbuttons.  Process the configuration.
     char config[1024];
     ssize_t nread;
     do {
         nread = read(fd.mFd, config, sizeof(config));
@@ -258,304 +340,246 @@ configureVButtons(FdHandler& data)
 
     if (0 > nread) {
         LOG("Error reading virtualkey configuration");
         return;
     }
 
     config[nread] = '\0';
 
-    LOG("Device %s has vbutton config '%s'", data.name, config);
+    LOG("Device %s has vbutton config '%s'", deviceName.string(), config);
 
-    char* startStr = config;
-    for (size_t i = 0; i < FdHandler::kMaxVButtons; ++i) {
-        FdHandler::VButton& vbutton = data.vbuttons[i];
-        char* token;
-        char* state;
-                
+    char* first = config;
+    char* magic;
+    char* state;
+    while ((magic = strtok_r(first, ":", &state))) {
         // XXX not clear what "0x01" is ... maybe a version
         // number?  See InputManager.java.
-        if (!(token = strtok_r(startStr, ":", &state)) ||
-            strcmp(token, "0x01")) {
+        if (strcmp(magic, "0x01")) {
             LOG("  magic 0x01 tag missing");
             break;
         }
-        startStr = NULL;
+        first = NULL;
 
-        if (!(token = strtok_r(NULL, ":", &state))) {
-            LOG("  failed to read keycode");
-            break;
-        }
-        vbutton.keyCode = atoi(token);
-
-        const char *centerX, *centerY, *width, *height;
-        if (!((centerX = strtok_r(NULL, ":", &state)) &&
+        const char *scanCode, *centerX, *centerY, *width, *height;
+        if (!((scanCode = strtok_r(NULL, ":", &state)) &&
+              (centerX = strtok_r(NULL, ":", &state)) &&
               (centerY = strtok_r(NULL, ":", &state)) &&
               (width = strtok_r(NULL, ":", &state)) &&
               (height = strtok_r(NULL, ":", &state)))) {
             LOG("  failed to read bound params");
             break;
         }
 
         // NB: these coordinates are in *screen* space, not input
         // space.  That means the values in /sys/board_config make
         // assumptions about how the raw input events are mapped
         // ... le sigh.
-        nsIntRect rect;
-        rect.width = atoi(width);
-        rect.height = atoi(height);
-        rect.x = atoi(centerX) - rect.width / 2;
-        rect.y = atoi(centerY) - rect.height / 2;
-        vbutton.buttonRect = rect;
+        VirtualKeyDefinition def;
+        def.scanCode = atoi(scanCode);
+        def.centerX = atoi(centerX);
+        def.centerY = atoi(centerY);
+        def.width = atoi(width);
+        def.height = atoi(height);
+        outVirtualKeyDefinitions.push(def);
 
         LOG("  configured vbutton code=%d at <x=%d,y=%d,w=%d,h=%d>",
-            vbutton.keyCode, rect.x, rect.y, rect.width, rect.height);
+            def.scanCode, def.centerX, def.centerY, def.width, def.height);
+    }
+}
+
+void
+GeckoInputReaderPolicy::getInputDeviceCalibration(const String8& deviceName,            InputDeviceCalibration& outCalibration)
+{
+    outCalibration.clear();
+}
+
+void
+GeckoInputReaderPolicy::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames)
+{
+    outExcludedDeviceNames.clear();
+}
+
+// GeckoInputDispatcher
+void
+GeckoInputDispatcher::dump(String8& dump)
+{
+}
+
+void
+GeckoInputDispatcher::dispatchOnce()
+{
+    UserInputData data;
+    {
+        MutexAutoLock lock(mQueueLock);
+        if (mEventQueue.empty())
+            return;
+
+        data = mEventQueue.front();
+        mEventQueue.pop();
+        if (!mEventQueue.empty())
+            gAppShell->NotifyNativeEvent();
+    }
+
+    switch (data.type) {
+    case UserInputData::MOTION_DATA: {
+        PRUint32 msg;
+        switch (data.action) {
+        case AMOTION_EVENT_ACTION_DOWN:
+            msg = NS_MOUSE_BUTTON_DOWN;
+            break;
+        case AMOTION_EVENT_ACTION_MOVE:
+            msg = NS_MOUSE_MOVE;
+            break;
+        case AMOTION_EVENT_ACTION_UP:
+            msg = NS_MOUSE_BUTTON_UP;
+            break;
+        }
+        sendMouseEvent(msg,
+                       data.timeMs,
+                       data.motion.coords.x,
+                       data.motion.coords.y);
+        break;
+    }
+    case UserInputData::KEY_DATA:
+        maybeSendKeyEvent(data.key.scanCode,
+                          data.action == AKEY_EVENT_ACTION_DOWN,
+                          data.timeMs);
+        break;
     }
 }
 
-static bool
-calibrateMultitouchDevice(FdHandler& data)
+
+void
+GeckoInputDispatcher::notifyConfigurationChanged(nsecs_t eventTime)
 {
-    if (data.calibrated)
-        return true;
-    if (gScreenBounds.IsEmpty()) {
-        // The framebuffer hasn't been initialized yet.  We *could*
-        // force it to be initialized here, but that's another patch.
-        LOG("Deferring multitouch calibrate, fb not ready");
-        return false;
-    }
+}
+
+static uint64_t
+nanosecsToMillisecs(nsecs_t nsecs)
+{
+    return nsecs / 1000000;
+}
 
-    struct input_absinfo xInfo, yInfo;
-    if (0 > ioctl(data.fd, EVIOCGABS(ABS_MT_POSITION_X), &xInfo) ||
-        0 > ioctl(data.fd, EVIOCGABS(ABS_MT_POSITION_Y), &yInfo)) {
-        LOG("Couldn't get absinfo for multitouch axes");
-        return false;
+void
+GeckoInputDispatcher::notifyKey(nsecs_t eventTime,
+                                int32_t deviceId,
+                                int32_t source,
+                                uint32_t policyFlags,
+                                int32_t action,
+                                int32_t flags,
+                                int32_t keyCode,
+                                int32_t scanCode,
+                                int32_t metaState,
+                                nsecs_t downTime)
+{
+    UserInputData data;
+    data.timeMs = nanosecsToMillisecs(eventTime);
+    data.type = UserInputData::KEY_DATA;
+    data.action = action;
+    data.flags = flags;
+    data.metaState = metaState;
+    data.key.keyCode = keyCode;
+    data.key.scanCode = scanCode;
+    {
+        MutexAutoLock lock(mQueueLock);
+        mEventQueue.push(data);
     }
-    LOG("Input coordinate bounds: xmin=%d, xmax=%d, ymin=%d, ymax=%d",
-        xInfo.minimum, xInfo.maximum, yInfo.minimum, yInfo.maximum);
-
-    data.inputMinX = xInfo.minimum;
-    data.inputMinY = yInfo.minimum;
-    data.inputToScreenScaleX =
-        float(gScreenBounds.width) / float(xInfo.maximum - xInfo.minimum);
-    data.inputToScreenScaleY =
-        float(gScreenBounds.height) / float(yInfo.maximum - yInfo.minimum);
-
-    configureVButtons(data);
-
-    data.calibrated = true;
-    return true;
+    gAppShell->NotifyNativeEvent();
 }
 
-static void
-multitouchHandler(int fd, FdHandler *data)
+void
+GeckoInputDispatcher::notifyMotion(nsecs_t eventTime,
+                                   int32_t deviceId,
+                                   int32_t source,
+                                   uint32_t policyFlags,
+                                   int32_t action,
+                                   int32_t flags,
+                                   int32_t metaState,
+                                   int32_t edgeFlags,
+                                   uint32_t pointerCount,
+                                   const int32_t* pointerIds,
+                                   const PointerCoords* pointerCoords,
+                                   float xPrecision,
+                                   float yPrecision,
+                                   nsecs_t downTime)
 {
-    if (!calibrateMultitouchDevice(*data))
-        return;
-
-    // The Linux's input documentation (Documentation/input/input.txt)
-    // says that we'll always read a multiple of sizeof(input_event) bytes here.
-    input_event events[16];
-    int event_count = read(fd, events, sizeof(events));
-    if (event_count < 0) {
-        LOG("Error reading in multitouchHandler");
-        return;
+    UserInputData data;
+    data.timeMs = nanosecsToMillisecs(eventTime);
+    data.type = UserInputData::MOTION_DATA;
+    data.action = action;
+    data.flags = flags;
+    data.metaState = metaState;
+    data.motion.coords = *pointerCoords;
+    {
+        MutexAutoLock lock(mQueueLock);
+        mEventQueue.push(data);
     }
-    MOZ_ASSERT(event_count % sizeof(input_event) == 0);
-
-    event_count /= sizeof(struct input_event);
-
-    for (int i = 0; i < event_count; i++) {
-        input_event *event = &events[i];
-
-        if (event->type == EV_ABS) {
-            if (data->mtState == FdHandler::MT_IGNORE)
-                continue;
-            if (data->mtState == FdHandler::MT_START)
-                data->mtState = FdHandler::MT_COLLECT;
+    gAppShell->NotifyNativeEvent();
+}
 
-            switch (event->code) {
-            case ABS_MT_TOUCH_MAJOR:
-                data->mtMajor = event->value;
-                break;
-            case ABS_MT_TOUCH_MINOR:
-            case ABS_MT_WIDTH_MAJOR:
-            case ABS_MT_WIDTH_MINOR:
-            case ABS_MT_ORIENTATION:
-            case ABS_MT_TOOL_TYPE:
-            case ABS_MT_BLOB_ID:
-            case ABS_MT_TRACKING_ID:
-            case ABS_MT_PRESSURE:
-                break;
-            case ABS_MT_POSITION_X:
-                data->mtX = data->inputXToScreenX(event->value);
-                break;
-            case ABS_MT_POSITION_Y:
-                data->mtY = data->inputYToScreenY(event->value);
-                break;
-            default:
-                VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
-                            event->type, event->code, event->value);
-                break;
-            }
-        } else if (event->type == EV_SYN) {
-            switch (event->code) {
-            case SYN_MT_REPORT:
-                if (data->mtState == FdHandler::MT_COLLECT)
-                    data->mtState = FdHandler::MT_IGNORE;
-                break;
-            case SYN_REPORT:
-                if (!data->mtMajor || data->mtState == FdHandler::MT_START) {
-                    data->mtDown = false;
-                    if (data->keyCode) {
-                        maybeSendKeyEvent(data->keyCode, data->mtDown,
-                                          event->time);
-                        data->keyCode = 0;
-                    } else {
-                        sendMouseEvent(NS_MOUSE_BUTTON_UP, event->time,
-                                       data->mtX, data->mtY);
-                    }
-                } else if (!data->mtDown) {
-                    int x = data->mtX, y = data->mtY;
-
-                    bool isKeyEvent = false;
-                    if (!gScreenBounds.Contains(x, y)) {
-                        // Off-screen mt down.  Should be a vbutton.
-                        for (size_t i = 0; i < FdHandler::kMaxVButtons; ++i) {
-                            const FdHandler::VButton& vbutton = data->vbuttons[i];
-                            if (vbutton.buttonRect.IsEmpty())
-                                break;
-
-                            if (vbutton.buttonRect.Contains(x, y)) {
-                                isKeyEvent = true;
-                                data->keyCode = vbutton.keyCode;
-                                break;
-                            }
-                        }
-                    }
-                    data->mtDown = true;
-
-                    if (isKeyEvent) {
-                        maybeSendKeyEvent(data->keyCode, data->mtDown,
-                                          event->time);
-                    } else {
-                        sendMouseEvent(NS_MOUSE_BUTTON_DOWN, event->time,
-                                       data->mtX, data->mtY);
-                    }
-                } else if (!data->keyCode) {
-                    sendMouseEvent(NS_MOUSE_MOVE, event->time,
-                                   data->mtX, data->mtY);
-                    data->mtDown = true;
-                }
-
-                data->mtState = FdHandler::MT_START;
-
-                break;
-            default:
-                VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
-                            event->type, event->code, event->value);
-
-            }
-        } else
-            VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
-                        event->type, event->code, event->value);
-    }
+void
+GeckoInputDispatcher::notifySwitch(nsecs_t when,
+                                   int32_t switchCode,
+                                   int32_t switchValue,
+                                   uint32_t policyFlags)
+{
 }
 
-static void
-singleTouchHandler(int fd, FdHandler *data)
-{
-    // The Linux's input documentation (Documentation/input/input.txt)
-    // says that we'll always read a multiple of sizeof(input_event) bytes here.
-    input_event events[16];
-    int event_count = read(fd, events, sizeof(events));
-    if (event_count < 0) {
-        LOG("Error reading in singleTouchHandler");
-        return;
-    }
-    MOZ_ASSERT(event_count % sizeof(input_event) == 0);
-
-    event_count /= sizeof(struct input_event);
-
-    for (int i = 0; i < event_count; i++) {
-        input_event *event = &events[i];
 
-        if (event->type == EV_KEY) {
-            switch (event->code) {
-            case BTN_TOUCH:
-                data->mtDown = event->value;
-                break;
-            default:
-                maybeSendKeyEvent(*event);
-            }
-        } else if (event->type == EV_ABS) {
-            switch (event->code) {
-            case ABS_X:
-                data->mtX = event->value;
-                break;
-            case ABS_Y:
-                data->mtY = event->value;
-                break;
-            default:
-                LOG("Got unknown st abs event type 0x%04x with code 0x%04x and value %d",
-                    event->type, event->code, event->value);
-            }
-        } else if (event->type == EV_SYN) {
-            if (data->mtState == FdHandler::MT_START) {
-                MOZ_ASSERT(data->mtDown);
-                sendMouseEvent(NS_MOUSE_BUTTON_DOWN, event->time,
-                               data->mtX, data->mtY);
-                data->mtState = FdHandler::MT_COLLECT;
-            } else if (data->mtDown) {
-                MOZ_ASSERT(data->mtDown);
-                sendMouseEvent(NS_MOUSE_MOVE, event->time,
-                               data->mtX, data->mtY);
-            } else {
-                MOZ_ASSERT(!data->mtDown);
-                sendMouseEvent(NS_MOUSE_BUTTON_UP, event->time,
-                                   data->mtX, data->mtY);
-                data->mtDown = false;
-                data->mtState = FdHandler::MT_START;
-            }
-        }
-    }
+int32_t
+GeckoInputDispatcher::injectInputEvent(const InputEvent* event,
+                                       int32_t injectorPid,
+                                       int32_t injectorUid,
+                                       int32_t syncMode,
+                                       int32_t timeoutMillis)
+{
+    return INPUT_EVENT_INJECTION_SUCCEEDED;
+}
+
+void
+GeckoInputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows)
+{
 }
 
-static void
-keyHandler(int fd, FdHandler *data)
+void
+GeckoInputDispatcher::setFocusedApplication(const InputApplication* inputApplication)
 {
-    input_event events[16];
-    ssize_t bytesRead = read(fd, events, sizeof(events));
-    if (bytesRead < 0) {
-        LOG("Error reading in keyHandler");
-        return;
-    }
-    MOZ_ASSERT(bytesRead % sizeof(input_event) == 0);
+}
+
+void
+GeckoInputDispatcher::setInputDispatchMode(bool enabled, bool frozen)
+{
+}
 
-    for (unsigned int i = 0; i < bytesRead / sizeof(struct input_event); i++) {
-        const input_event &e = events[i];
+status_t
+GeckoInputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+                                           bool monitor)
+{
+    return OK;
+}
 
-        if (e.type == EV_SYN) {
-            // Ignore this event; it just signifies that a key was pressed.
-            continue;
-        }
-
-        maybeSendKeyEvent(e);
-    }
+status_t
+GeckoInputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel)
+{
+    return OK;
 }
 
 nsAppShell::nsAppShell()
     : mNativeCallbackRequest(false)
     , mHandlers()
 {
     gAppShell = this;
 }
 
 nsAppShell::~nsAppShell()
 {
+    status_t result = mReaderThread->requestExitAndWait();
+    if (result)
+        LOG("Could not stop reader thread - %d", result);
     gAppShell = NULL;
 }
 
 nsresult
 nsAppShell::Init()
 {
     nsresult rv = nsBaseAppShell::Init();
     NS_ENSURE_SUCCESS(rv, rv);
@@ -564,62 +588,25 @@ nsAppShell::Init()
     NS_ENSURE_TRUE(epollfd >= 0, NS_ERROR_UNEXPECTED);
 
     int ret = pipe2(signalfds, O_NONBLOCK);
     NS_ENSURE_FALSE(ret, NS_ERROR_UNEXPECTED);
 
     rv = AddFdHandler(signalfds[0], pipeHandler, "");
     NS_ENSURE_SUCCESS(rv, rv);
 
-    DIR *dir = opendir("/dev/input");
-    NS_ENSURE_TRUE(dir, NS_ERROR_UNEXPECTED);
-
-#define IS_BIT_SET(bit, flags) (flags[bit >> 3] & (1 << (bit & 0x7)))
-
-    struct dirent *entry;
-    while ((entry = readdir(dir))) {
-        char entryName[64];
-        char entryPath[MAXPATHLEN];
-        if (snprintf(entryPath, sizeof(entryPath),
-                     "/dev/input/%s", entry->d_name) < 0) {
-            LOG("Couldn't generate path while enumerating input devices!");
-            continue;
-        }
-        int fd = open(entryPath, O_RDONLY);
-        if (ioctl(fd, EVIOCGNAME(sizeof(entryName)), entryName) >= 0)
-            LOG("Found device %s - %s", entry->d_name, entryName);
-        else
-            continue;
-
-        FdHandlerCallback handlerFunc = NULL;
+    mEventHub = new EventHub();
+    mReaderPolicy = new GeckoInputReaderPolicy();
+    mDispatcher = new GeckoInputDispatcher();
 
-        char flags[(NS_MAX(ABS_MAX, KEY_MAX) + 1) / 8];
-        if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
-            IS_BIT_SET(ABS_MT_POSITION_X, flags)) {
+    mReader = new InputReader(mEventHub, mReaderPolicy, mDispatcher);
+    mReaderThread = new InputReaderThread(mReader);
 
-            LOG("Found multitouch input device");
-            handlerFunc = multitouchHandler;
-        } else if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
-                   IS_BIT_SET(ABS_X, flags)) {
-            LOG("Found single touch input device");
-            handlerFunc = singleTouchHandler;
-        } else if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(flags)), flags) >= 0) {
-            LOG("Found key input device");
-            handlerFunc = keyHandler;
-        }
-
-        // Register the handler, if we have one.
-        if (!handlerFunc)
-            continue;
-
-        rv = AddFdHandler(fd, handlerFunc, entryName);
-        if (NS_FAILED(rv))
-            LOG("Failed to add fd to epoll fd");
-    }
-
+    status_t result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
+    NS_ENSURE_FALSE(result, NS_ERROR_UNEXPECTED);
     return rv;
 }
 
 nsresult
 nsAppShell::AddFdHandler(int fd, FdHandlerCallback handlerFunc,
                          const char* deviceName)
 {
     epoll_event event = {
@@ -650,16 +637,18 @@ nsAppShell::ProcessNextNativeEvent(bool 
 
     int event_count;
     if ((event_count = epoll_wait(epollfd, events, 16,  mayWait ? -1 : 0)) <= 0)
         return true;
 
     for (int i = 0; i < event_count; i++)
         mHandlers[events[i].data.u32].run();
 
+    mDispatcher->dispatchOnce();
+
     // NativeEventCallback always schedules more if it needs it
     // so we can coalesce these.
     // See the implementation in nsBaseAppShell.cpp for more info
     if (mNativeCallbackRequest) {
         mNativeCallbackRequest = false;
         NativeEventCallback();
     }
 
--- a/widget/gonk/nsAppShell.h
+++ b/widget/gonk/nsAppShell.h
@@ -33,94 +33,59 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsAppShell_h
 #define nsAppShell_h
 
+#include <queue>
+
+#include "mozilla/Mutex.h"
 #include "nsBaseAppShell.h"
 #include "nsRect.h"
 #include "nsTArray.h"
 
+#include "utils/RefBase.h"
+
 namespace mozilla {
 bool ProcessNextEvent();
 void NotifyEvent();
 }
 
 extern bool gDrawRequest;
 
 class FdHandler;
 typedef void(*FdHandlerCallback)(int, FdHandler *);
 
 class FdHandler {
 public:
     FdHandler()
-        : mtState(MT_START)
-        , keyCode(0)
-        , mtDown(false)
-        , calibrated(false)
     {
         memset(name, 0, sizeof(name));
     }
 
     int fd;
     char name[64];
     FdHandlerCallback func;
-    enum mtStates {
-        MT_START,
-        MT_COLLECT,
-        MT_IGNORE
-    } mtState;
-    int mtX, mtY;
-    int mtMajor;
-    int keyCode;
-    bool mtDown;
-    // FIXME/bug 712973: we should be using libui here instead of
-    // recreating all that logic ourselves.  Please don't extend the
-    // hacks here further than what's below.
-    bool calibrated;
-    // Multitouch events are delivered to us in "input space", which
-    // is a coordinate space defined by the multitouch device driver.
-    // The coordinate space has top-left at P_min = <inputMinX,
-    // inputMinY> when in normal-portrait orientation.  The input
-    // device and the screen might have different resolutions.  The
-    // resolution difference is Scale = <inputToScreenScaleX,
-    // inputToScreenScaleY>.  So going from input to screen space
-    // (when in normal portrait orientation) is an affine transform
-    // defined by
-    //
-    //   P_screen = Scale * (P_input - P_min)
-    //
-    int inputMinX, inputMinY;
-    float inputToScreenScaleX, inputToScreenScaleY;
-    // Some touch devices use virtual buttons instead of hardware
-    // buttons.  When the device uses vbuttons, we convert touch
-    // events into key events of type |keyCode| when the start of the
-    // touch is within |buttonRect|.  |buttonRect| must be disjoint
-    // from the screen rect.
-    static const size_t kMaxVButtons = 4;
-    struct VButton {
-        nsIntRect buttonRect;   // in screen space
-        int keyCode;
-    } vbuttons[kMaxVButtons];
-
     void run()
     {
         func(fd, this);
     }
+};
 
-    int inputXToScreenX(int inputX) {
-        return inputToScreenScaleX * (inputX - inputMinX);
-    }
-    int inputYToScreenY(int inputY) {
-        return inputToScreenScaleY * (inputY - inputMinY);
-    }
-};
+namespace android {
+class EventHub;
+class InputReader;
+class InputReaderThread;
+}
+
+class GeckoInputReaderPolicy;
+class GeckoInputDispatcher;
 
 class nsAppShell : public nsBaseAppShell {
 public:
     nsAppShell();
 
     nsresult Init();
     virtual bool ProcessNextNativeEvent(bool maywait);
 
@@ -133,12 +98,18 @@ protected:
 
 private:
     nsresult AddFdHandler(int fd, FdHandlerCallback handlerFunc,
                           const char* deviceName);
 
     // This is somewhat racy but is perfectly safe given how the callback works
     bool mNativeCallbackRequest;
     nsTArray<FdHandler> mHandlers;
+
+    android::sp<android::EventHub>               mEventHub;
+    android::sp<GeckoInputReaderPolicy> mReaderPolicy;
+    android::sp<GeckoInputDispatcher>   mDispatcher;
+    android::sp<android::InputReader>            mReader;
+    android::sp<android::InputReaderThread>      mReaderThread;
 };
 
 #endif /* nsAppShell_h */
 
--- a/widget/gonk/nsWidgetFactory.cpp
+++ b/widget/gonk/nsWidgetFactory.cpp
@@ -42,49 +42,54 @@
 #include "nsWidgetsCID.h"
 #include "nsAppShell.h"
 
 #include "nsWindow.h"
 #include "nsLookAndFeel.h"
 #include "nsAppShellSingleton.h"
 #include "nsScreenManagerGonk.h"
 #include "nsIdleServiceGonk.h"
+#include "nsTransferable.h"
 
 #include "nsHTMLFormatConverter.h"
 #include "nsXULAppAPI.h"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerGonk)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceGonk)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
 
 NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
 NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
 NS_DEFINE_NAMED_CID(NS_CHILD_CID);
 NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
+NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
     { &kNS_WINDOW_CID, false, NULL, nsWindowConstructor },
     { &kNS_CHILD_CID, false, NULL, nsWindowConstructor },
     { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor },
     { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerGonkConstructor },
     { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor },
     { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceGonkConstructor },
+    { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor },
     { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
     { "@mozilla.org/widgets/window/gonk;1", &kNS_WINDOW_CID },
     { "@mozilla.org/widgets/child_window/gonk;1", &kNS_CHILD_CID },
     { "@mozilla.org/widget/appshell/gonk;1", &kNS_APPSHELL_CID },
     { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
     { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
     { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
+    { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
     { NULL }
 };
 
 static void
 nsWidgetGonkModuleDtor()
 {
     nsLookAndFeel::Shutdown();
     nsAppShellShutdown();
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2818,17 +2818,17 @@ nsCycleCollector::GCIfNeeded(bool aForce
     }
 
 #ifdef COLLECT_TIME_DEBUG
     PRTime start = PR_Now();
 #endif
     // rt->Collect() must be called from the main thread,
     // because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
     // which returns false if not in the main thread.
-    rt->Collect();
+    rt->Collect(js::gcreason::CC_FORCED, nsGCNormal);
 #ifdef COLLECT_TIME_DEBUG
     printf("cc: GC() took %lldms\n", (PR_Now() - start) / PR_USEC_PER_MSEC);
 #endif
 }
 
 bool
 nsCycleCollector::PrepareForCollection(nsTArray<PtrInfo*> *aWhiteNodes)
 {
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -101,19 +101,20 @@ struct nsCycleCollectionJSRuntime : publ
     virtual void NotifyEnterMainThread() = 0;
 
     /**
      * Should we force a JavaScript GC before a CC?
      */
     virtual bool NeedCollect() = 0;
 
     /**
-     * Runs the JavaScript GC.
+     * Runs the JavaScript GC. |reason| is a gcreason::Reason from jsfriendapi.h.
+     * |kind| is a nsGCType from nsIXPConnect.idl.
      */
-    virtual void Collect(bool shrinkingGC = false) = 0;
+    virtual void Collect(PRUint32 reason, PRUint32 kind) = 0;
 };
 
 #ifdef DEBUG
 void nsCycleCollector_DEBUG_shouldBeFreed(nsISupports *n);
 void nsCycleCollector_DEBUG_wasFreed(nsISupports *n);
 #endif
 
 // Helpers for interacting with language-identified scripts
--- a/xulrunner/config/mozconfigs/win32/xulrunner
+++ b/xulrunner/config/mozconfigs/win32/xulrunner
@@ -1,9 +1,8 @@
 export MOZILLA_OFFICIAL=1
 export JAVA_HOME=/d/jdk1.6.0_14
 
 ac_add_options --enable-application=xulrunner
 ac_add_options --enable-jemalloc
-ac_add_options --disable-installer
 ac_add_options --disable-tests
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
--- a/xulrunner/config/mozconfigs/win64/xulrunner
+++ b/xulrunner/config/mozconfigs/win64/xulrunner
@@ -1,12 +1,11 @@
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 export MOZILLA_OFFICIAL=1
 export JAVA_HOME=/d/jdk1.6.0_14
 
 ac_add_options --enable-application=xulrunner
 ac_add_options --enable-jemalloc
-ac_add_options --disable-installer
 ac_add_options --disable-tests
 
 mk_add_options MOZ_MAKE_FLAGS=-j1