Bug 725095 - Merge off-main-thread compositor from Maple. IGNORE BAD COMMIT MESSAGES
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 14 Mar 2012 11:18:15 -0400
changeset 89356 936ef50fa498d4185a15d7b75324daf1d4fa35c9
parent 89355 8017faf1070605a14e38dacd1ef14ab030381b1d (current diff)
parent 89004 5cddc46dcaf3b8b869685a840a61ad4604702f61 (diff)
child 89357 7e158ac25de30772e07aca77c2c0de19e42541e5
child 89389 10d7baa4aff02bc6ed52f62879814f989dfc469d
push id22242
push userkgupta@mozilla.com
push dateWed, 14 Mar 2012 15:19:09 +0000
treeherdermozilla-central@936ef50fa498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs725095
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 725095 - Merge off-main-thread compositor from Maple. IGNORE BAD COMMIT MESSAGES
dom/base/Navigator.cpp
dom/base/nsWindowMemoryReporter.cpp
dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl
embedding/android/GeckoEvent.java
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jscntxt.h
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoEvent.java
mobile/android/base/Makefile.in
mobile/android/chrome/content/bindings.xml
mobile/android/chrome/jar.mn
mobile/android/chrome/tests/Makefile.in
mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js
mobile/android/chrome/tests/addons/browser_install1_1/install.rdf
mobile/android/chrome/tests/addons/browser_install1_2/install.rdf
mobile/android/chrome/tests/addons/browser_install1_3/install.rdf
mobile/android/chrome/tests/addons/browser_locale1/boostrap.js
mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest
mobile/android/chrome/tests/addons/browser_locale1/install.rdf
mobile/android/chrome/tests/browser_addons.js
mobile/android/chrome/tests/browser_addons_locales.js
mobile/android/chrome/tests/browser_appmenu.js
mobile/android/chrome/tests/browser_autocomplete.html
mobile/android/chrome/tests/browser_autocomplete.js
mobile/android/chrome/tests/browser_autocompletesearch.js
mobile/android/chrome/tests/browser_awesomescreen.js
mobile/android/chrome/tests/browser_blank_01.html
mobile/android/chrome/tests/browser_blank_02.html
mobile/android/chrome/tests/browser_blank_03.html
mobile/android/chrome/tests/browser_bookmarks.js
mobile/android/chrome/tests/browser_bookmarks_star.js
mobile/android/chrome/tests/browser_bookmarks_tags.js
mobile/android/chrome/tests/browser_click_content.html
mobile/android/chrome/tests/browser_click_content.js
mobile/android/chrome/tests/browser_contacts.js
mobile/android/chrome/tests/browser_contentpopup.html
mobile/android/chrome/tests/browser_contentpopup.js
mobile/android/chrome/tests/browser_dragger.js
mobile/android/chrome/tests/browser_escape.js
mobile/android/chrome/tests/browser_find.js
mobile/android/chrome/tests/browser_focus.html
mobile/android/chrome/tests/browser_focus.js
mobile/android/chrome/tests/browser_forms.html
mobile/android/chrome/tests/browser_forms.js
mobile/android/chrome/tests/browser_formsZoom.html
mobile/android/chrome/tests/browser_formsZoom.js
mobile/android/chrome/tests/browser_history.js
mobile/android/chrome/tests/browser_install.xml
mobile/android/chrome/tests/browser_localepicker.js
mobile/android/chrome/tests/browser_localepicker_escape.js
mobile/android/chrome/tests/browser_localerepository.js
mobile/android/chrome/tests/browser_localerepository_buildid.js
mobile/android/chrome/tests/browser_localerepository_pref.js
mobile/android/chrome/tests/browser_mainui.js
mobile/android/chrome/tests/browser_navigation.js
mobile/android/chrome/tests/browser_preferences_fulltoggle.js
mobile/android/chrome/tests/browser_preferences_text.js
mobile/android/chrome/tests/browser_rect.js
mobile/android/chrome/tests/browser_rememberPassword.js
mobile/android/chrome/tests/browser_scroll.html
mobile/android/chrome/tests/browser_scroll.js
mobile/android/chrome/tests/browser_scrollbar.js
mobile/android/chrome/tests/browser_scrollbar.sjs
mobile/android/chrome/tests/browser_select.html
mobile/android/chrome/tests/browser_select.js
mobile/android/chrome/tests/browser_sessionstore.js
mobile/android/chrome/tests/browser_sidebars.js
mobile/android/chrome/tests/browser_tabs.js
mobile/android/chrome/tests/browser_tap_content.html
mobile/android/chrome/tests/browser_tap_contentedit.html
mobile/android/chrome/tests/browser_tapping.js
mobile/android/chrome/tests/browser_tapping_edit.js
mobile/android/chrome/tests/browser_test.js
mobile/android/chrome/tests/browser_thumbnails.js
mobile/android/chrome/tests/browser_title.sjs
mobile/android/chrome/tests/browser_upgrade.rdf
mobile/android/chrome/tests/browser_viewport.js
mobile/android/chrome/tests/browser_viewport.sjs
mobile/android/chrome/tests/browser_vkb.js
mobile/android/chrome/tests/head.js
mobile/android/chrome/tests/locales_list.sjs
mobile/android/chrome/tests/mock_autocomplete.json
mobile/android/chrome/tests/remote_autocomplete.js
mobile/android/chrome/tests/remote_contentpopup.js
mobile/android/chrome/tests/remote_focus.js
mobile/android/chrome/tests/remote_forms.js
mobile/android/chrome/tests/remote_formsZoom.js
mobile/android/chrome/tests/remote_head.js
mobile/android/chrome/tests/remote_vkb.js
modules/libpref/src/init/all.js
mozglue/android/APKOpen.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/nsAppShell.cpp
--- a/.hgtags
+++ b/.hgtags
@@ -73,8 +73,9 @@ 462c726144bc1fb45b61e774f64ac5d61b4e047c
 54bfd8bf682e295ffd7f22fa921ca343957b6c1c AURORA_BASE_20111108
 a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220
 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 0000000000000000000000000000000000000000 AURORA_BASE_20120131
 0000000000000000000000000000000000000000 AURORA_BASE_20120131
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
+b6627f28b7ec17e1b46a594df0f780d3a40847e4 FIREFOX_AURORA_13_BASE
--- a/accessible/src/base/AccIterator.cpp
+++ b/accessible/src/base/AccIterator.cpp
@@ -36,16 +36,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "AccIterator.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccessible.h"
 
 #include "mozilla/dom/Element.h"
+#include "nsBindingManager.h"
+
+using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 AccIterator::AccIterator(nsAccessible *aAccessible,
                          filters::FilterFuncPtr aFilterFunc,
                          IterationType aIterationType) :
@@ -124,27 +127,31 @@ RelatedAccIterator::Next()
   if (!mProviders)
     return nsnull;
 
   while (mIndex < mProviders->Length()) {
     nsDocAccessible::AttrRelProvider* provider = (*mProviders)[mIndex++];
 
     // Return related accessible for the given attribute and if the provider
     // content is in the same binding in the case of XBL usage.
-    if (provider->mRelAttr == mRelAttr &&
-        (!mBindingParent ||
-         mBindingParent == provider->mContent->GetBindingParent())) {
-      nsAccessible* related = mDocument->GetAccessible(provider->mContent);
-      if (related)
-        return related;
+    if (provider->mRelAttr == mRelAttr) {
+      nsIContent* bindingParent = provider->mContent->GetBindingParent();
+      bool inScope = mBindingParent == bindingParent ||
+        mBindingParent == provider->mContent;
 
-      // If the document content is pointed by relation then return the document
-      // itself.
-      if (provider->mContent == mDocument->GetContent())
-        return mDocument;
+      if (inScope) {
+        nsAccessible* related = mDocument->GetAccessible(provider->mContent);
+        if (related)
+          return related;
+
+        // If the document content is pointed by relation then return the document
+        // itself.
+        if (provider->mContent == mDocument->GetContent())
+          return mDocument;
+      }
     }
   }
 
   return nsnull;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -266,28 +273,20 @@ XULDescriptionIterator::Next()
   return nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IDRefsIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
-  mCurrIdx(0)
+  mCurrIdx(0), mContent(aContent)
 {
-  if (!aContent->IsInDoc() ||
-      !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
-    return;
-
-  if (aContent->IsInAnonymousSubtree()) {
-    mXBLDocument = do_QueryInterface(aContent->OwnerDoc());
-    mBindingParent = do_QueryInterface(aContent->GetBindingParent());
-  } else {
-    mDocument = aContent->OwnerDoc();
-  }
+  if (mContent->IsInDoc())
+    mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
 }
 
 const nsDependentSubstring
 IDRefsIterator::NextID()
 {
   for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
     if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
       break;
@@ -319,30 +318,55 @@ IDRefsIterator::NextElem()
   }
 
   return nsnull;
 }
 
 nsIContent*
 IDRefsIterator::GetElem(const nsDependentSubstring& aID)
 {
-  if (mXBLDocument) {
-    // If content is anonymous subtree then use "anonid" attribute to get
-    // elements, otherwise search elements in DOM by ID attribute.
-
-    nsCOMPtr<nsIDOMElement> refElm;
-    mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
-                                                 NS_LITERAL_STRING("anonid"),
-                                                 aID,
-                                                 getter_AddRefs(refElm));
-    nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
-    return refContent;
+  // Get elements in DOM tree by ID attribute if this is an explicit content.
+  // In case of bound element check its anonymous subtree.
+  if (!mContent->IsInAnonymousSubtree()) {
+    dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID);
+    if (refElm || !mContent->OwnerDoc()->BindingManager()->GetBinding(mContent))
+      return refElm;
   }
 
-  return mDocument->GetElementById(aID);
+  // If content is in anonymous subtree or an element having anonymous subtree
+  // then use "anonid" attribute to get elements in anonymous subtree.
+  nsCOMPtr<nsIDOMElement> refDOMElm;
+  nsCOMPtr<nsIDOMDocumentXBL> xblDocument =
+    do_QueryInterface(mContent->OwnerDoc());
+
+  // Check inside the binding the element is contained in.
+  nsIContent* bindingParent = mContent->GetBindingParent();
+  if (bindingParent) {
+    nsCOMPtr<nsIDOMElement> bindingParentElm = do_QueryInterface(bindingParent);
+    xblDocument->GetAnonymousElementByAttribute(bindingParentElm,
+                                                NS_LITERAL_STRING("anonid"),
+                                                aID,
+                                                getter_AddRefs(refDOMElm));
+    nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
+    if (refElm)
+      return refElm;
+  }
+
+  // Check inside the binding of the element.
+  if (mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) {
+    nsCOMPtr<nsIDOMElement> elm = do_QueryInterface(mContent);
+    xblDocument->GetAnonymousElementByAttribute(elm,
+                                                NS_LITERAL_STRING("anonid"),
+                                                aID,
+                                                getter_AddRefs(refDOMElm));
+    nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
+    return refElm;
+  }
+
+  return nsnull;
 }
 
 nsAccessible*
 IDRefsIterator::Next()
 {
   nsIContent* nextElm = NextElem();
   return nextElm ? GetAccService()->GetAccessible(nextElm, nsnull) : nsnull;
 }
--- a/accessible/src/base/AccIterator.h
+++ b/accessible/src/base/AccIterator.h
@@ -286,21 +286,18 @@ public:
   virtual nsAccessible* Next();
 
 private:
   IDRefsIterator();
   IDRefsIterator(const IDRefsIterator&);
   IDRefsIterator operator = (const IDRefsIterator&);
 
   nsString mIDs;
+  nsIContent* mContent;
   nsAString::index_type mCurrIdx;
-
-  nsIDocument* mDocument;
-  nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
-  nsCOMPtr<nsIDOMElement> mBindingParent;
 };
 
 /**
  * Iterator that points to a single accessible returning it on the first call
  * to Next().
  */
 class SingleAccIterator : public AccIterable
 {
--- a/accessible/src/msaa/CAccessibleComponent.cpp
+++ b/accessible/src/msaa/CAccessibleComponent.cpp
@@ -49,23 +49,16 @@
 
 #include "nsString.h"
 
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMNSRGBAColor.h"
 
 using namespace mozilla::a11y;
 
-enum {
-  IA2AlphaShift = 24,
-  IA2RedShift = 16,
-  IA2GreenShift = 8,
-  IA2BlueShift = 0
-};
-
 // IUnknown
 
 STDMETHODIMP
 CAccessibleComponent::QueryInterface(REFIID iid, void** ppv)
 {
   *ppv = NULL;
 
   if (IID_IAccessibleComponent == iid) {
@@ -125,115 +118,45 @@ CAccessibleComponent::get_locationInPare
   *aY = y - parenty;
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
-CAccessibleComponent::get_foreground(IA2Color *aForeground)
+CAccessibleComponent::get_foreground(IA2Color* aForeground)
 {
 __try {
-  return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("color"), aForeground);
+  nsRefPtr<nsAccessible> acc(do_QueryObject(this));
+  if (acc->IsDefunct())
+    return E_FAIL;
+
+  nsIFrame* frame = acc->GetFrame();
+  if (frame)
+    *aForeground = frame->GetStyleColor()->mColor;
+
+  return S_OK;
+
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
 
   return E_FAIL;
 }
 
 STDMETHODIMP
-CAccessibleComponent::get_background(IA2Color *aBackground)
+CAccessibleComponent::get_background(IA2Color* aBackground)
 {
 __try {
-  return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("background-color"),
-                                     aBackground);
+  nsRefPtr<nsAccessible> acc(do_QueryObject(this));
+  if (acc->IsDefunct())
+    return E_FAIL;
+
+  nsIFrame* frame = acc->GetFrame();
+  if (frame)
+    *aBackground = frame->GetStyleBackground()->mBackgroundColor;
+
+  return S_OK;
+
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
 
   return E_FAIL;
 }
 
-HRESULT
-CAccessibleComponent::GetARGBValueFromCSSProperty(const nsAString& aPropName,
-                                                  IA2Color *aColorValue)
-{
-__try {
-  *aColorValue = 0;
-
-  nsRefPtr<nsAccessible> acc(do_QueryObject(this));
-  if (acc->IsDefunct())
-    return E_FAIL;
-
-  nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
-    nsWinUtils::GetComputedStyleDeclaration(acc->GetContent());
-  NS_ENSURE_STATE(styleDecl);
-
-  nsCOMPtr<nsIDOMCSSValue> cssGenericValue;
-  styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue));
-
-  nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue =
-    do_QueryInterface(cssGenericValue);
-  if (!cssValue)
-    return E_FAIL;
-
-  nsCOMPtr<nsIDOMRGBColor> rgbColor;
-  nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
-  if (NS_FAILED(rv) || !rgbColor)
-    return GetHRESULT(rv);
-
-  nsCOMPtr<nsIDOMNSRGBAColor> rgbaColor(do_QueryInterface(rgbColor));
-  if (!rgbaColor)
-    return GetHRESULT(rv);
-
-  // get alpha
-  nsCOMPtr<nsIDOMCSSPrimitiveValue> alphaValue;
-  rv = rgbaColor->GetAlpha(getter_AddRefs(alphaValue));
-  if (NS_FAILED(rv) || !alphaValue)
-    return GetHRESULT(rv);
-
-  float alpha = 0.0;
-  rv = alphaValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &alpha);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  // get red
-  nsCOMPtr<nsIDOMCSSPrimitiveValue> redValue;
-  rv = rgbaColor->GetRed(getter_AddRefs(redValue));
-  if (NS_FAILED(rv) || !redValue)
-    return GetHRESULT(rv);
-
-  float red = 0.0;
-  rv = redValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &red);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  // get green
-  nsCOMPtr<nsIDOMCSSPrimitiveValue> greenValue;
-  rv = rgbaColor->GetGreen(getter_AddRefs(greenValue));
-  if (NS_FAILED(rv) || !greenValue)
-    return GetHRESULT(rv);
-
-  float green = 0.0;
-  rv = greenValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &green);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  // get blue
-  nsCOMPtr<nsIDOMCSSPrimitiveValue> blueValue;
-  rv = rgbaColor->GetBlue(getter_AddRefs(blueValue));
-  if (NS_FAILED(rv) || !blueValue)
-    return GetHRESULT(rv);
-
-  float blue = 0.0;
-  rv = blueValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &blue);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  // compose ARGB value
-  *aColorValue = (((IA2Color) blue) << IA2BlueShift) |
-                 (((IA2Color) green) << IA2GreenShift) |
-                 (((IA2Color) red) << IA2RedShift) |
-                 (((IA2Color) (alpha * 0xff)) << IA2AlphaShift);
-  return S_OK;
-
-} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
-  return E_FAIL;
-}
-
--- a/accessible/src/msaa/CAccessibleComponent.h
+++ b/accessible/src/msaa/CAccessibleComponent.h
@@ -60,20 +60,12 @@ public:
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_foreground(
       /* [retval][out] */ IA2Color *foreground);
 
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_background(
       /* [retval][out] */ IA2Color *background);
 
   // nsISupports
   NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) = 0;
-
-protected:
-
-  /**
-   * Return ARGB value for CSS property like 'color' or 'background-color'.
-   */
-  HRESULT GetARGBValueFromCSSProperty(const nsAString& aPropName,
-                                      IA2Color *aColorValue);
 };
 
 #endif
 
--- a/accessible/tests/mochitest/relations.js
+++ b/accessible/tests/mochitest/relations.js
@@ -73,17 +73,17 @@ function testRelation(aIdentifier, aRelT
     while (enumerate.hasMoreElements()) {
       var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
       if (targets[idx] == relatedAcc) {
         isFound = true;
         break;
       }
     }
 
-    ok(isFound, relatedIds[idx] + " is not a target of" + relDescr);
+    ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr);
   }
 
   // Check if all obtained targets are given related accessibles.
   var enumerate = actualTargets.enumerate();
   while (enumerate.hasMoreElements()) {
     var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
     for (var idx = 0; idx < targets.length && relatedAcc != targets[idx]; idx++);
 
--- a/accessible/tests/mochitest/relations/Makefile.in
+++ b/accessible/tests/mochitest/relations/Makefile.in
@@ -41,18 +41,20 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/relations
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
+		test_bindings.xhtml \
 		test_embeds.xul \
 		test_general.html \
 		test_general.xul \
 		test_tabbrowser.xul \
 		test_tree.xul \
+		test_ui_modalprompt.html \
 		test_update.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/relations/test_bindings.xhtml
@@ -0,0 +1,103 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+  <title>Accessible relations for bindings</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <style>
+    .button {
+      -moz-binding: url('#custombutton');
+    }
+
+    .button2 {
+      -moz-binding: url('#custombutton2');
+    }
+  </style>
+
+  <bindings xmlns="http://www.mozilla.org/xbl">
+    <binding id="custombutton">
+      <content aria-labelledby="button.label label">
+        <label xmlns="http://www.w3.org/1999/xhtml" anonid="button.label">
+          anon label
+        </label>
+        <button xmlns="http://www.w3.org/1999/xhtml" anonid="button.button"
+                aria-labelledby="button.label label">
+          a button
+        </button>
+        <div xmlns="http://www.w3.org/1999/xhtml"
+             anonid="button.button2" class="button2"
+             aria-labelledby="button.label"></div>
+        <div xmlns="http://www.w3.org/1999/xhtml"
+             anonid="button.button3" class="button2"></div>
+      </content>
+    </binding>
+    <binding id="custombutton2">
+      <content aria-labelledby="button2.label">
+        <label xmlns="http://www.w3.org/1999/xhtml" anonid="button2.label">
+          nested anon label
+        </label>
+      </content>
+    </binding>
+  </bindings>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../relations.js"></script>
+
+  <script type="application/javascript">
+    function doTests()
+    {
+      var button = document.getElementById("button");
+      var anonLabel = document.
+        getAnonymousElementByAttribute(button, "anonid", "button.label");
+      var anonButton = document.
+        getAnonymousElementByAttribute(button, "anonid", "button.button");
+      var anonButton2 = document.
+        getAnonymousElementByAttribute(button, "anonid", "button.button2");
+      var anonButton3 = document.
+        getAnonymousElementByAttribute(button, "anonid", "button.button3");
+      var anonAnonLabel = document.
+        getAnonymousElementByAttribute(anonButton3, "anonid", "button2.label");
+
+      testRelation("label", RELATION_LABEL_FOR, button);
+      testRelation(anonLabel, RELATION_LABEL_FOR, [button, anonButton, anonButton2]);
+      testRelation(button, RELATION_LABELLED_BY, [anonLabel, "label"]);
+      testRelation(anonButton, RELATION_LABELLED_BY, anonLabel);
+      testRelation(anonButton2, RELATION_LABELLED_BY, anonLabel);
+      testRelation(anonButton3, RELATION_LABELLED_BY, anonAnonLabel);
+      testRelation(anonAnonLabel, RELATION_LABEL_FOR, anonButton3);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=421242"
+     title="Allow relations in anonymous content for binding parent">
+    Mozilla Bug 421242
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <label id="label">explicit label</label>
+  <div id="button" class="button"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/relations/test_ui_modalprompt.html
@@ -0,0 +1,95 @@
+<html>
+
+<head>
+  <title>Modal prompts</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../relations.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+  <script type="application/javascript"
+          src="../browser.js"></script>
+
+  <script type="application/javascript">
+    function showAlert()
+    {
+      this.eventSeq = [
+        {
+          type: EVENT_SHOW,
+          match: function(aEvent)
+          {
+            return aEvent.accessible.role == ROLE_DIALOG;
+          }
+        }
+      ];
+
+      this.invoke = function showAlert_invoke()
+      {
+        window.setTimeout(
+          function()
+          {
+            currentTabDocument().defaultView.alert("hello");
+          }, 0);
+      }
+
+      this.check = function showAlert_finalCheck(aEvent)
+      {
+        var dialog = aEvent.accessible.DOMNode;
+        var info = dialog.ui.infoBody;
+        testRelation(info, RELATION_DESCRIPTION_FOR, dialog);
+        testRelation(dialog, RELATION_DESCRIBED_BY, info);
+      }
+
+      this.getID = function showAlert_getID()
+      {
+        return "show alert";
+      }
+    }
+
+    //gA11yEventDumpToConsole = true; // debug
+
+    var gQueue = null;
+    function doTests()
+    {
+      gQueue = new eventQueue();
+      gQueue.push(new showAlert());
+      gQueue.onFinish = function()
+      {
+        synthesizeKey("VK_RETURN", {}, browserWindow());
+        closeBrowserWindow();
+      }
+      gQueue.invoke(); // will call SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    openBrowserWindow(doTests);
+  </script>
+
+</head>
+
+<body id="body">
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=661293"
+     title="The tabmodalprompt dialog's prompt label doesn't get the text properly associated for accessibility">
+    Mozilla Bug 661293
+  </a>
+  <br>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+</body>
+</html>
--- a/browser/base/content/test/browser_pageInfo.js
+++ b/browser/base/content/test/browser_pageInfo.js
@@ -1,46 +1,38 @@
 function test() {
   waitForExplicitFinish();
 
   var pageInfo;
+
   gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function () {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+  gBrowser.selectedBrowser.addEventListener("load", function loadListener() {
+    gBrowser.selectedBrowser.removeEventListener("load", loadListener, true);
+
+    Services.obs.addObserver(observer, "page-info-dialog-loaded", false);
     pageInfo = BrowserPageInfo();
-    Services.obs.addObserver(observer, "page-info-dialog-loaded", false);
   }, true);
   content.location =
     "https://example.com/browser/browser/base/content/test/feed_tab.html";
 
   function observer(win, topic, data) {
-    if (topic != "page-info-dialog-loaded")
-      return;
-
-    Services.obs.removeObserver(observer, topic);
+    Services.obs.removeObserver(observer, "page-info-dialog-loaded");
     handlePageInfo();
   }
 
-  function $(aId) { return pageInfo.document.getElementById(aId) };
-
   function handlePageInfo() {
-    var feedTab = $("feedTab");
-    var feedListbox = $("feedListbox");
-
-    ok(feedListbox, "Feed list is null (feeds tab is broken)");
+    ok(pageInfo.document.getElementById("feedTab"), "Feed tab");
+    let feedListbox = pageInfo.document.getElementById("feedListbox");
+    ok(feedListbox, "Feed list");
 
     var feedRowsNum = feedListbox.getRowCount();
-
-    ok(feedRowsNum == 3, "Number of feeds listed: " +
-                         feedRowsNum + ", should be 3");
-
+    is(feedRowsNum, 3, "Number of feeds listed");
 
     for (var i = 0; i < feedRowsNum; i++) {
       let feedItem = feedListbox.getItemAtIndex(i);
-      ok(feedItem.getAttribute("name") == (i+1), 
-         "Name given: " + feedItem.getAttribute("name") + ", should be " + (i+1));
+      is(feedItem.getAttribute("name"), i + 1, "Feed name");
     }
 
     pageInfo.close();
     gBrowser.removeCurrentTab();
     finish();
   }
 }
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-13.0a1
+14.0a1
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -61,16 +61,31 @@
   }
 
   #main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
     background-image: @toolbarShadowOnTab@,
                       -moz-linear-gradient(white, @toolbarHighlight@ 50%),
                       -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
+  #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme),
+  #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme) {
+    border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3);
+  }
+
+  #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme):not([focused]):hover,
+  #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme):not([focused]):hover {
+    border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4);
+  }
+
+  #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme)[focused],
+  #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme)[focused] {
+    border-color: hsla(206,100%,60%,.65) hsla(206,100%,55%,.65) hsla(206,100%,50%,.65);
+  }
+
   #sidebar-splitter {
     border: 0;
     -moz-border-end: 1px solid #A9B7C9;
     min-width: 0;
     width: 3px;
     background-color: transparent;
     -moz-margin-start: -3px;
     position: relative;
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by milestone.pl.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-13.0a1
+14.0a1
--- a/content/base/test/test_XHR_timeout.js
+++ b/content/base/test/test_XHR_timeout.js
@@ -271,22 +271,23 @@ var TestRequests = [
 
   new RequestTracker(true, "timeout set to expiring value after load fires", 5000, 4000, 1000),
   new RequestTracker(true, "timeout set to expired value before load fires", 5000, 2000, 1000),
   new RequestTracker(true, "timeout set to non-expiring value after timeout fires", 1000, 2000, 5000),
 
   // Aborted requests.
   new AbortedRequest(false),
   new AbortedRequest(true, -1),
-  new AbortedRequest(true, 0),
-  new AbortedRequest(true, 1000),
   new AbortedRequest(true, 5000),
 ];
 
 var MainThreadTestRequests = [
+  new AbortedRequest(true, 0),
+  new AbortedRequest(true, 1000),
+
   // Synchronous requests.
   SyncRequestSettingTimeoutAfterOpen,
   SyncRequestSettingTimeoutBeforeOpen
 ];
 
 var WorkerThreadTestRequests = [
   // Simple timeouts.
   new RequestTracker(false, "no time out scheduled, load fires normally", 0),
--- a/content/events/test/test_eventctors.html
+++ b/content/events/test/test_eventctors.html
@@ -321,20 +321,58 @@ ok(e.type, "hello", "Wrong event type!")
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
 is(e.detail, 1, "detail should be 1");
 is(e.view, window, "view should be window");
 document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
-// UIEvent
+// StorageEvent
 
 try {
-  e = new UIEvent();
+  e = new StorageEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new StorageEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.key, "", "key should be ''");
+is(e.oldValue, null, "oldValue should be null");
+is(e.newValue, null, "newValue should be null");
+is(e.url, "", "url should be ''");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new StorageEvent("hello",
+  { bubbles: true, cancelable: true, key: "key",
+    oldValue: "oldValue", newValue: "newValue", url: "url",
+    storageArea: localStorage });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.key, "key", "Wrong value");
+is(e.oldValue, "oldValue", "Wrong value");
+is(e.newValue, "newValue", "Wrong value");
+is(e.url, "url", "Wrong value");
+is(e.storageArea, localStorage, "Wrong value");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+// MouseEvent
+
+try {
+  e = new MouseEvent();
 } catch(exp) {
   ex = true;
 }
 ok(ex, "First parameter is required!");
 ex = false;
 
 e = new MouseEvent("hello");
 ok(e.type, "hello", "Wrong event type!");
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -562,16 +562,23 @@ Navigator::JavaEnabled(bool* aReturn)
       *aReturn = true;
       break;
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+Navigator::TaintEnabled(bool *aReturn)
+{
+  *aReturn = false;
+  return NS_OK;
+}
+
 void
 Navigator::RefreshMIMEArray()
 {
   if (mMimeTypes) {
     mMimeTypes->Refresh();
   }
 }
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1417,19 +1417,16 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   
   NS_DEFINE_CLASSINFO_DATA(GeoPosition, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS) 
   
   NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(GeoPositionAddress, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozBatteryManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -4015,20 +4012,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(GeoPosition, nsIDOMGeoPosition)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPosition)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(GeoPositionCoords, nsIDOMGeoPositionCoords)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(GeoPositionAddress, nsIDOMGeoPositionAddress)
-     DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionAddress)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(GeoPositionError, nsIDOMGeoPositionError)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozBatteryManager, nsIDOMMozBatteryManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozBatteryManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -417,17 +417,16 @@ DOMCI_CLASS(DataContainerEvent)
 // event used for cross-domain message-passing and for server-sent events in
 // HTML5
 DOMCI_CLASS(MessageEvent)
 
 // Geolocation
 DOMCI_CLASS(GeoGeolocation)
 DOMCI_CLASS(GeoPosition)
 DOMCI_CLASS(GeoPositionCoords)
-DOMCI_CLASS(GeoPositionAddress)
 DOMCI_CLASS(GeoPositionError)
 
 DOMCI_CLASS(MozBatteryManager)
 
 DOMCI_CLASS(MozPowerManager)
 DOMCI_CLASS(MozWakeLock)
 
 DOMCI_CLASS(MozSmsManager)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3156,16 +3156,54 @@ nsJSContext::CycleCollectNow(nsICycleCol
                                           PR_USEC_PER_MSEC,
                                         sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
                                         sRemovedPurples));
     nsCOMPtr<nsIConsoleService> cs =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
+
+    NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
+      NS_LL("{ \"duration\": %llu, ")
+         NS_LL("\"suspected\": %lu, ")
+         NS_LL("\"visited\": { ")
+             NS_LL("\"RCed\": %lu, ")
+             NS_LL("\"GCed\": %lu }, ")
+         NS_LL("\"collected\": { ")
+             NS_LL("\"RCed\": %lu, ")
+             NS_LL("\"GCed\": %lu }, ")
+         NS_LL("\"waiting_for_gc\": %lu, ")
+         NS_LL("\"forced_gc\": %d, ")
+         NS_LL("\"forget_skippable\": { ")
+             NS_LL("\"times_before_cc\": %lu, ")
+             NS_LL("\"min\": %lu, ")
+             NS_LL("\"max\": %lu, ")
+             NS_LL("\"avg\": %lu, ")
+             NS_LL("\"total\": %lu, ")
+             NS_LL("\"removed\": %lu } ")
+       NS_LL("}"));
+    nsString json;
+    json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(),
+                                        (now - start) / PR_USEC_PER_MSEC, suspected,
+                                        ccResults.mVisitedRefCounted, ccResults.mVisitedGCed,
+                                        ccResults.mFreedRefCounted, ccResults.mFreedGCed,
+                                        sCCollectedWaitingForGC,
+                                        ccResults.mForcedGC,
+                                        sForgetSkippableBeforeCC,
+                                        sMinForgetSkippableTime / PR_USEC_PER_MSEC,
+                                        sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
+                                        (sTotalForgetSkippableTime / cleanups) /
+                                          PR_USEC_PER_MSEC,
+                                        sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
+                                        sRemovedPurples));
+    nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+    if (observerService) {
+      observerService->NotifyObservers(nsnull, "cycle-collection-statistics", json.get());
+    }
   }
   sMinForgetSkippableTime = PR_UINT32_MAX;
   sMaxForgetSkippableTime = 0;
   sTotalForgetSkippableTime = 0;
   sRemovedPurples = 0;
   sForgetSkippableBeforeCC = 0;
   sCleanupSinceLastGC = true;
   sNeedsFullCC = false;
@@ -3412,35 +3450,63 @@ nsJSContext::KillCCTimer()
 }
 
 void
 nsJSContext::GC(js::gcreason::Reason aReason)
 {
   PokeGC(aReason);
 }
 
+class NotifyGCEndRunnable : public nsRunnable
+{
+  nsString mMessage;
+
+public:
+  NotifyGCEndRunnable(const nsString& aMessage) : mMessage(aMessage) {}
+
+  NS_DECL_NSIRUNNABLE
+};
+
+NS_IMETHODIMP
+NotifyGCEndRunnable::Run()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+  if (!observerService) {
+    return NS_OK;
+  }
+
+  const jschar oomMsg[3] = { '{', '}', 0 };
+  const jschar *toSend = mMessage.get() ? mMessage.get() : oomMsg;
+  observerService->NotifyObservers(nsnull, "garbage-collection-statistics", toSend);
+
+  return NS_OK;
+}
+
 static void
 DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescription &aDesc)
 {
   NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
 
-  if (aDesc.logMessage && sPostGCEventsToConsole) {
+  if (aProgress == js::GC_CYCLE_END && sPostGCEventsToConsole) {
     PRTime now = PR_Now();
     PRTime delta = 0;
     if (sFirstCollectionTime) {
       delta = now - sFirstCollectionTime;
     } else {
       sFirstCollectionTime = now;
     }
 
     NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f) %s");
-    nsString msg;
+    nsString msg, gcstats;
+    gcstats.Adopt(aDesc.formatMessage(aRt));
     msg.Adopt(nsTextFormatter::smprintf(kFmt.get(),
                                         double(delta) / PR_USEC_PER_SEC,
-                                        aDesc.logMessage));
+                                        gcstats.get()));
     nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
   }
 
   // Prevent cycle collections and shrinking during incremental GC.
   if (aProgress == js::GC_CYCLE_BEGIN) {
@@ -3458,16 +3524,21 @@ DOMGCSliceCallback(JSRuntime *aRt, js::G
 
   if (aProgress == js::GC_CYCLE_END) {
     // May need to kill the inter-slice GC timer
     nsJSContext::KillGCTimer();
 
     sCCollectedWaitingForGC = 0;
     sCleanupSinceLastGC = false;
 
+    nsString json;
+    json.Adopt(aDesc.formatJSON(aRt));
+    nsRefPtr<NotifyGCEndRunnable> notify = new NotifyGCEndRunnable(json);
+    NS_DispatchToMainThread(notify);
+
     if (aDesc.isCompartment) {
       // 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 it is
       // probably a time of heavy activity and we want to delay
       // the full GC, but we do want it to happen eventually.
       nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
     }
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -48,17 +48,17 @@ NS_IMPL_ISUPPORTS1(nsWindowMemoryReporte
 /* static */
 void
 nsWindowMemoryReporter::Init()
 {
   // The memory reporter manager is going to own this object.
   NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter());
 }
 
-static bool
+static void
 AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
 {
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
   nsCOMPtr<nsIURI> uri;
 
   if (doc) {
     uri = doc->GetDocumentURI();
   }
@@ -66,31 +66,29 @@ AppendWindowURI(nsGlobalWindow *aWindow,
   if (!uri) {
     nsIPrincipal *principal = aWindow->GetPrincipal();
 
     if (principal) {
       principal->GetURI(getter_AddRefs(uri));
     }
   }
 
-  if (!uri) {
-    return false;
-  }
-
-  nsCString spec;
-  uri->GetSpec(spec);
+  if (uri) {
+    nsCString spec;
+    uri->GetSpec(spec);
 
-  // A hack: replace forward slashes with '\\' so they aren't
-  // treated as path separators.  Users of the reporters
-  // (such as about:memory) have to undo this change.
-  spec.ReplaceChar('/', '\\');
+    // A hack: replace forward slashes with '\\' so they aren't
+    // treated as path separators.  Users of the reporters
+    // (such as about:memory) have to undo this change.
+    spec.ReplaceChar('/', '\\');
 
-  aStr += spec;
-
-  return true;
+    aStr += spec;
+  } else {
+    aStr += NS_LITERAL_CSTRING("[system]");
+  }
 }
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
 
 static nsresult
 CollectWindowReports(nsGlobalWindow *aWindow,
                      nsWindowSizes *aWindowTotalSizes,
                      nsIMemoryMultiReporterCallback *aCb,
@@ -99,135 +97,107 @@ CollectWindowReports(nsGlobalWindow *aWi
   // DOM window objects fall into one of three categories:
   // - "active" windows are currently either displayed in an active
   //   tab, or a child of such a window.
   // - "cached" windows are in the fastback cache.
   // - "other" windows are closed (or navigated away from w/o being
   //   cached) yet held alive by either a website or our code. The
   //   latter case may be a memory leak, but not necessarily.
   //
-  // For inner windows we show how much memory the window and its
-  // document etc use, and we report those per URI, where the URI is
-  // the document URI, if available, or the codebase of the principal
-  // in the window. In the case where we're unable to find a URI we're
-  // dealing with a chrome window with no document in it (or
-  // somesuch), and for that we make the URI be the string "[system]".
+  // For each window we show how much memory the window and its
+  // document, etc, use, and we report those per URI, where the URI is
+  // the document URI, if available, or the codebase of the principal in
+  // the window. In the case where we're unable to find a URI we're
+  // dealing with a chrome window with no document in it (or somesuch),
+  // and for that we make the URI be the string "[system]".
   //
-  // For outer windows we simply group them all together and just show
-  // the combined count and amount of memory used, which is generally
-  // a constant amount per window (since all the actual data lives in
-  // the inner window).
+  // Outer windows are lumped in with inner windows, because the amount
+  // of memory used by outer windows is small.
+  //
+  // The path we give to the reporter callback for "active" and "cached"
+  // windows (both inner and outer) is as follows:
   //
-  // The path we give to the reporter callback for inner windows are
-  // as follows:
+  //   explicit/window-objects/top(<top-outer-uri>, id=<top-outer-id>)/<category>/window(<window-uri>)/...
   //
-  //   explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
+  // The path we give for "other" windows is as follows:
+  //
+  //   explicit/window-objects/top(none)/window(<window-uri>)/...
   //
   // Where:
-  // - <category> is active, cached, or other, as described above.
+  // - <category> is "active" or "cached", as described above.
   // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
   //   the top outer window (i.e. tab, or top level chrome window).
-  // - <top-inner-id> is the window id of the top window's inner
-  //   window.
-  // - <id> is the window id of the inner window in question.
-  // - <uri> is the URI per above description.
+  // - <top-inner-uri> is the URI of the top outer window.  Excepting
+  //   special windows (such as browser.xul or hiddenWindow.html) it's
+  //   what the address bar shows for the tab.
+  // - <window-uri> is the URI of aWindow.
   //
-  // Exposing the window ids is done to get logical grouping in
-  // about:memory, and also for debuggability since one can get to the
-  // nsGlobalWindow for a window id by calling the static method
-  // nsGlobalWindow::GetInnerWindowWithId(id) (or
-  // GetOuterWindowWithId(id) in a debugger.
-  //
-  // For outer windows we simply use:
-  // 
-  //   explicit/window-objects/<category>/outer-windows
-  //
-  // Which gives us simple counts of how many outer windows (and their
-  // combined sizes) per category.
+  // Exposing the top-outer-id ensures that each tab gets its own
+  // sub-tree, even if multiple tabs are showing the same URI.
 
   nsCAutoString windowPath("explicit/window-objects/");
 
-  nsIDocShell *docShell = aWindow->GetDocShell();
-
   nsGlobalWindow *top = aWindow->GetTop();
-  nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
-  aWindow->SizeOfIncludingThis(&windowSizes);
+  windowPath += NS_LITERAL_CSTRING("top(");
+  if (top) {
+    AppendWindowURI(top, windowPath);
+    windowPath += NS_LITERAL_CSTRING(", id=");
+    windowPath.AppendInt(top->WindowID());
+  } else {
+    windowPath += NS_LITERAL_CSTRING("none");
+  }
+  windowPath += NS_LITERAL_CSTRING(")/");
 
-  if (docShell && aWindow->IsFrozen()) {
-    windowPath += NS_LITERAL_CSTRING("cached/");
-  } else if (docShell) {
-    windowPath += NS_LITERAL_CSTRING("active/");
+  nsIDocShell *docShell = aWindow->GetDocShell();
+  if (docShell) {
+    MOZ_ASSERT(top, "'cached' or 'active' window lacks a top window");
+    windowPath += aWindow->IsFrozen() ? NS_LITERAL_CSTRING("cached/")
+                                      : NS_LITERAL_CSTRING("active/");
   } else {
-    windowPath += NS_LITERAL_CSTRING("other/");
+    MOZ_ASSERT(!top, "'other' window has a top window");
   }
 
-  if (aWindow->IsInnerWindow()) {
-    windowPath += NS_LITERAL_CSTRING("top=");
-
-    if (top) {
-      windowPath.AppendInt(top->WindowID());
-
-      nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
-      if (topInner) {
-        windowPath += NS_LITERAL_CSTRING(" (inner=");
-        windowPath.AppendInt(topInner->WindowID());
-        windowPath += NS_LITERAL_CSTRING(")");
-      }
-    } else {
-      windowPath += NS_LITERAL_CSTRING("none");
-    }
+  windowPath += NS_LITERAL_CSTRING("window(");
+  AppendWindowURI(aWindow, windowPath);
+  windowPath += NS_LITERAL_CSTRING(")");
 
-    windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
-    windowPath.AppendInt(aWindow->WindowID());
-    windowPath += NS_LITERAL_CSTRING(", uri=");
-
-    if (!AppendWindowURI(aWindow, windowPath)) {
-      windowPath += NS_LITERAL_CSTRING("[system]");
-    }
-
-    windowPath += NS_LITERAL_CSTRING(")");
-  } else {
-    // Combine all outer windows per section (active/cached/other) as
-    // they basically never contain anything of interest, and are
-    // always pretty much the same size.
-
-    windowPath += NS_LITERAL_CSTRING("outer-windows");
-  }
-
-#define REPORT(_path1, _path2, _amount, _desc)                                \
+#define REPORT(_pathTail, _amount, _desc)                                     \
   do {                                                                        \
     if (_amount > 0) {                                                        \
-        nsCAutoString path(_path1);                                           \
-        path += _path2;                                                       \
+        nsCAutoString path(windowPath);                                       \
+        path += _pathTail;                                                    \
         nsresult rv;                                                          \
         rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\
                       nsIMemoryReporter::UNITS_BYTES, _amount,                \
                       NS_LITERAL_CSTRING(_desc), aClosure);                   \
         NS_ENSURE_SUCCESS(rv, rv);                                            \
     }                                                                         \
   } while (0)
 
-  REPORT(windowPath, "/dom", windowSizes.mDOM,
+  nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
+  aWindow->SizeOfIncludingThis(&windowSizes);
+
+  REPORT("/dom", windowSizes.mDOM,
          "Memory used by a window and the DOM within it.");
   aWindowTotalSizes->mDOM += windowSizes.mDOM;
 
-  REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
+  REPORT("/style-sheets", windowSizes.mStyleSheets,
          "Memory used by style sheets within a window.");
   aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
 
-  REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
+  REPORT("/layout/arenas", windowSizes.mLayoutArenas,
          "Memory used by layout PresShell, PresContext, and other related "
          "areas within a window.");
   aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
 
-  REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
+  REPORT("/layout/style-sets", windowSizes.mLayoutStyleSets,
          "Memory used by style sets within a window.");
   aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;
 
-  REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
+  REPORT("/layout/text-runs", windowSizes.mLayoutTextRuns,
          "Memory used for text-runs (glyph layout) in the PresShell's frame "
          "tree, within a window.");
   aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;
 
 #undef REPORT
 
   return NS_OK;
 }
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -20,17 +20,17 @@ const Ci = Components.interfaces;
 Cu.import("resource://gre/modules/Services.jsm");
 
 const DB_NAME = "contacts";
 const DB_VERSION = 1;
 const STORE_NAME = "contacts";
 
 function ContactDB(aGlobal) {
   debug("Constructor");
-  this._indexedDB = aGlobal.mozIndexedDB;
+  this._global = aGlobal;
 }
 
 ContactDB.prototype = {
 
   // Cache the DB
   db: null,
 
   close: function close() {
@@ -49,17 +49,17 @@ ContactDB.prototype = {
     if (this.db) {
       debug("ensureDB: already have a database, returning early.");
       callback(this.db);
       return;
     }
 
     let self = this;
     debug("try to open database:" + DB_NAME + " " + DB_VERSION);
-    let request = this._indexedDB.open(DB_NAME, DB_VERSION);
+    let request = this._global.mozIndexedDB.open(DB_NAME, DB_VERSION);
     request.onsuccess = function (event) {
       debug("Opened database:", DB_NAME, DB_VERSION);
       self.db = event.target.result;
       self.db.onversionchange = function(event) {
         debug("WARNING: DB modified from a different window.");
       }
       callback(self.db);
     };
@@ -111,24 +111,32 @@ ContactDB.prototype = {
     objectStore.createIndex("nickname",   "properties.nickname",   { unique: false, multiEntry: true });
     objectStore.createIndex("name",       "properties.name",       { unique: false, multiEntry: true });
     objectStore.createIndex("familyName", "properties.familyName", { unique: false, multiEntry: true });
     objectStore.createIndex("givenName",  "properties.givenName",  { unique: false, multiEntry: true });
     objectStore.createIndex("tel",        "properties.tel",        { unique: false, multiEntry: true });
     objectStore.createIndex("email",      "properties.email",      { unique: false, multiEntry: true });
     objectStore.createIndex("note",       "properties.note",       { unique: false, multiEntry: true });
 
+    objectStore.createIndex("nicknameLowerCase",   "search.nickname",   { unique: false, multiEntry: true });
+    objectStore.createIndex("nameLowerCase",       "search.name",       { unique: false, multiEntry: true });
+    objectStore.createIndex("familyNameLowerCase", "search.familyName", { unique: false, multiEntry: true });
+    objectStore.createIndex("givenNameLowerCase",  "search.givenName",  { unique: false, multiEntry: true });
+    objectStore.createIndex("telLowerCase",        "search.tel",        { unique: false, multiEntry: true });
+    objectStore.createIndex("emailLowerCase",      "search.email",      { unique: false, multiEntry: true });
+    objectStore.createIndex("noteLowerCase",       "search.note",       { unique: false, multiEntry: true });
+
     debug("Created object stores and indexes");
   },
 
   /**
    * Start a new transaction.
    * 
    * @param txn_type
-   *        Type of transaction (e.g. IDBTransaction.READ_WRITE)
+   *        Type of transaction (e.g. "readwrite")
    * @param callback
    *        Function to call when the transaction is available. It will
    *        be invoked with the transaction and the 'contacts' object store.
    * @param successCb [optional]
    *        Success callback to call on a successful transaction commit.
    * @param failureCb [optional]
    *        Error callback to call when an error is encountered.
    */
@@ -166,17 +174,16 @@ ContactDB.prototype = {
             failureCb("UnknownError");
             break;
         }
       };
       callback(txn, store);
     }, failureCb);
   },
 
-  // Todo: add searchfields. "Tom" should be a result with T, t, To, to...
   makeImport: function makeImport(aContact) {
     let contact = {};
     contact.properties = {
       name:            [],
       honorificPrefix: [],
       givenName:       [],
       additionalName:  [],
       familyName:      [],
@@ -192,28 +199,51 @@ ContactDB.prototype = {
       bday:            null,
       note:            [],
       impp:            [],
       anniversary:     null,
       sex:             null,
       genderIdentity:  null
     };
 
+    contact.search = {
+      name:            [],
+      honorificPrefix: [],
+      givenName:       [],
+      additionalName:  [],
+      familyName:      [],
+      honorificSuffix: [],
+      nickname:        [],
+      email:           [],
+      category:        [],
+      tel:             [],
+      org:             [],
+      note:            [],
+      impp:            []
+    };
+
     for (let field in aContact.properties) {
       contact.properties[field] = aContact.properties[field];
+      // Add search fields
+      if (aContact.properties[field] && contact.search[field]) {
+        for (let i = 0; i <= aContact.properties[field].length; i++) {
+          if (aContact.properties[field][i])
+            contact.search[field].push(aContact.properties[field][i].toLowerCase());
+        }
+      }
     }
+    debug("contact:" + JSON.stringify(contact));
 
     contact.updated = aContact.updated;
     contact.published = aContact.published;
     contact.id = aContact.id;
 
     return contact;
   },
 
-  // Needed to remove searchfields
   makeExport: function makeExport(aRecord) {
     let contact = {};
     contact.properties = aRecord.properties;
 
     for (let field in aRecord.properties)
       contact.properties[field] = aRecord.properties[field];
 
     contact.updated = aRecord.updated;
@@ -229,17 +259,17 @@ ContactDB.prototype = {
     if (!record.published) {
       record.published = new Date();
     }
     record.updated = new Date();
   },
 
   saveContact: function saveContact(aContact, successCb, errorCb) {
     let contact = this.makeImport(aContact);
-    this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
+    this.newTxn("readwrite", function (txn, store) {
       debug("Going to update" + JSON.stringify(contact));
 
       // Look up the existing record and compare the update timestamp.
       // If no record exists, just add the new entry.
       let newRequest = store.get(contact.id);
       newRequest.onsuccess = function (event) {
         if (!event.target.result) {
           debug("new record!")
@@ -258,24 +288,24 @@ ContactDB.prototype = {
             store.put(contact);
           }
         }
       }.bind(this);
     }.bind(this), successCb, errorCb);
   },
 
   removeContact: function removeContact(aId, aSuccessCb, aErrorCb) {
-    this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
+    this.newTxn("readwrite", function (txn, store) {
       debug("Going to delete" + aId);
       store.delete(aId);
     }, aSuccessCb, aErrorCb);
   },
 
   clear: function clear(aSuccessCb, aErrorCb) {
-    this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
+    this.newTxn("readwrite", function (txn, store) {
       debug("Going to clear all!");
       store.clear();
     }, aSuccessCb, aErrorCb);
   },
 
   /**
    * @param successCb
    *        Callback function to invoke with result array.
@@ -292,21 +322,19 @@ ContactDB.prototype = {
    *        - sortBy
    *        - sortOrder
    *        - startIndex
    */
   find: function find(aSuccessCb, aFailureCb, aOptions) {
     debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n");
 
     let self = this;
-    this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (txn, store) {
-      if (aOptions && aOptions.filterOp == "equals") {
+    this.newTxn("readonly", function (txn, store) {
+      if (aOptions && (aOptions.filterOp == "equals" || aOptions.filterOp == "contains")) {
         self._findWithIndex(txn, store, aOptions);
-      } else if (aOptions && aOptions.filterBy) {
-        self._findWithSearch(txn, store, aOptions);
       } else {
         self._findAll(txn, store, aOptions);
       }
     }, aSuccessCb, aFailureCb);
   },
 
   _findWithIndex: function _findWithIndex(txn, store, options) {
     debug("_findWithIndex: " + options.filterValue +" " + options.filterOp + " " + options.filterBy + " ");
@@ -329,78 +357,39 @@ ContactDB.prototype = {
     }
 
     let filter_keys = fields.slice();
     for (let key = filter_keys.shift(); key; key = filter_keys.shift()) {
       let request;
       if (key == "id") {
         // store.get would return an object and not an array
         request = store.getAll(options.filterValue);
-      } else {
+      } else if (options.filterOp == "equals") {
         debug("Getting index: " + key);
+        // case sensitive
         let index = store.index(key);
         request = index.getAll(options.filterValue, options.filterLimit);
+      } else {
+        // not case sensitive
+        let tmp = options.filterValue.toLowerCase();
+        let range = this._global.IDBKeyRange.bound(tmp, tmp + "\uFFFF");
+        let index = store.index(key + "LowerCase");
+        request = index.getAll(range, options.filterLimit);
       }
       if (!txn.result)
         txn.result = {};
 
       request.onsuccess = function (event) {
         debug("Request successful. Record count:" + event.target.result.length);
         for (let i in event.target.result)
           txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
       }.bind(this);
     }
   },
 
-  // Will be replaced by _findWithIndex once all searchfields are added.
-  _findWithSearch: function _findWithSearch(txn, store, options) {
-    debug("_findWithSearch:" + options.filterValue + options.filterOp)
-    store.getAll().onsuccess = function (event) {
-      debug("Request successful." + event.target.result);
-      txn.result = event.target.result.filter(function (record) {
-        let properties = record.properties;
-        for (let i = 0; i < options.filterBy.length; i++) {
-          let field = options.filterBy[i];
-          if (!properties[field])
-              continue;
-          let value = '';
-          switch (field) {
-            case "name":
-            case "familyName":
-            case "givenName":
-            case "nickname":
-            case "email":
-            case "tel":
-            case "note":
-              value = [f for each (f in [properties[field]])].join("\n") || '';
-              break;
-            default:
-              value = properties[field];
-              debug("unknown field: " + field);
-          }
-          let match = false;
-          switch (options.filterOp) {
-            case "icontains":
-              match = value.toLowerCase().indexOf(options.filterValue.toLowerCase()) != -1;
-              break;
-            case "contains":
-              match = value.indexOf(options.filterValue) != -1;
-              break;
-            case "equals":
-              match = value == options.filterValue;
-              break
-          }
-          if (match)
-            return true;
-        }
-        return false;
-      }).map(this.makeExport.bind(this));
-    }.bind(this);
-  },
-
   _findAll: function _findAll(txn, store, options) {
     debug("ContactDB:_findAll:  " + JSON.stringify(options));
     if (!txn.result)
       txn.result = {};
 
     store.getAll(null, options.filterLimit).onsuccess = function (event) {
       debug("Request successful. Record count:", event.target.result.length);
       for (let i in event.target.result)
--- a/dom/contacts/tests/test_contacts_basics.html
+++ b/dom/contacts/tests/test_contacts_basics.html
@@ -41,17 +41,17 @@ var adr2 = {
   locality: "locality2",
   region: "region2",
   postalCode: "postal code2",
   countryName: "country2"
 };
 
 var properties1 = {
   name: "Testname1",
-  familyName: "TestFamilyName",
+  familyName: ["TestFamilyName","Wagner"],
   givenName: ["Test1","Test2"],
   nickname: "nicktest",
   tel: ["123456"],
   adr: adr1
 };
 
 var properties2 = {
   name: ["dummyName", "dummyName2"],
@@ -207,16 +207,76 @@ var steps = [
       ok(createResult1.id, "The contact now has an ID.");
       sample_id1 = createResult1.id;
       checkContacts(properties1, createResult1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
+    ok(true, "Retrieving by substring");
+    var options = {filterBy: ["name"],
+                   filterOp: "contains",
+                   filterValue: properties1.name.substring(0,3)};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      checkContacts(createResult1, properties1);
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring2");
+    var options = {filterBy: ["givenName"],
+                   filterOp: "contains",
+                   filterValue: properties1.givenName[0].substring(0,3)};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      checkContacts(createResult1, properties1);
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring3");
+    var options = {filterBy: ["name", "givenName"],
+                   filterOp: "contains",
+                   filterValue: properties1.givenName[0].substring(0,3)};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      checkContacts(createResult1, properties1);
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring3, Testing multi entry");
+    var options = {filterBy: ["name", "givenName", "familyName"],
+                   filterOp: "contains",
+                   filterValue: properties1.familyName[1].substring(0,3).toLowerCase()};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      checkContacts(createResult1, properties1);
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
     ok(true, "Retrieving all contacts");
     req = mozContacts.find({});
     req.onsuccess = function() {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(createResult1, findResult1);
       ok(findResult1.updated, "Has updated field");
@@ -301,32 +361,32 @@ var steps = [
       }
       req2.onerror = onFailure;
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by query");
     var options = {filterBy: ["name", "email"],
-                   filterOp: "icontains",
+                   filterOp: "contains",
                    filterValue: properties1.name[0].substring(0,4)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(findResult1, createResult1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by query");
     var options = {filterBy: ["nickname", "email"],
-                   filterOp: "icontains",
+                   filterOp: "contains",
                    filterValue: properties1.nickname};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(findResult1, createResult1);
       next();
@@ -424,32 +484,32 @@ var steps = [
       ok(req.result.length == 2, "Found exactly 2 contact.");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     console.log("Searching contacts by query1");
     var options = {filterBy: ["name", "email"],
-                   filterOp: "icontains",
+                   filterOp: "contains",
                    filterValue: properties1.name[0].substring(0, 4)}
     req = mozContacts.find(options)
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(findResult1, createResult1);
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by query2");
     var options = {filterBy: ["name", "email"],
-                   filterOp: "icontains",
+                   filterOp: "contains",
                    filterValue: properties2.name[0].substring(0, 4)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.adr.length == 2, "Adr length 2");
       checkContacts(findResult1, createResult2);
       next();
@@ -533,27 +593,41 @@ var steps = [
       ok(req.result.length == 10, "10 Entries.");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Retrieving all contacts2");
     var options = {filterBy: ["name"],
-                   filterOp: "icontains",
-                   filterValue: properties2.name[0].substring(0, 4)};
-    req = mozContacts.find({});
+                   filterOp: "contains",
+                   filterValue: properties1.name[0].substring(0, 4)};
+    req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 100, "100 Entries.");
       checkContacts(createResult1, req.result[99]);
       next();
     }
     req.onerror = onFailure;
   },
   function () {
+    ok(true, "Retrieving all contacts3");
+    var options = {filterBy: ["name", "givenName", "tel", "email", "note"],
+                   filterOp: "contains",
+                   filterValue: properties1.name[0].substring(0, 4),
+                   filterLimit: 15 };
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 15, "15 Entries.");
+      checkContacts(createResult1, req.result[10]);
+      next();
+    }
+    req.onerror = onFailure;
+  },
+  function () {
     ok(true, "Deleting database");
     req = mozContacts.clear();
     req.onsuccess = function () {
       clearTemps();
       next();
     }
     req.onerror = onFailure;
   },
@@ -583,17 +657,17 @@ var steps = [
       ok(cloned.givenName == "Tom", "New Name");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Retrieving all contacts");
     var options = {filterBy: ["name"],
-                   filterOp: "icontains",
+                   filterOp: "contains",
                    filterValue: properties2.name[0].substring(0, 4)};
     req = mozContacts.find({});
     req.onsuccess = function () {
       ok(req.result.length == 2, "2 Entries.");
       next();
     }
     req.onerror = onFailure;
   },
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -458,17 +458,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCurs
 DOMCI_DATA(IDBCursor, IDBCursor)
 DOMCI_DATA(IDBCursorWithValue, IDBCursor)
 
 NS_IMETHODIMP
 IDBCursor::GetDirection(nsAString& aDirection)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  switch(mDirection) {
+  switch (mDirection) {
     case NEXT:
       aDirection.AssignLiteral("next");
       break;
     case NEXT_UNIQUE:
       aDirection.AssignLiteral("nextunique");
       break;
     case PREV:
       aDirection.AssignLiteral("prev");
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -527,17 +527,17 @@ IDBTransaction::GetDb(nsIIDBDatabase** a
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBTransaction::GetMode(nsAString& aMode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  switch(mMode) {
+  switch (mMode) {
     case READ_ONLY:
       aMode.AssignLiteral("readonly");
       break;
     case READ_WRITE:
       aMode.AssignLiteral("readwrite");
       break;
     case VERSION_CHANGE:
       aMode.AssignLiteral("versionchange");
--- a/dom/interfaces/base/nsIDOMNavigator.idl
+++ b/dom/interfaces/base/nsIDOMNavigator.idl
@@ -34,17 +34,17 @@
  * 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"
 
-[scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)]
+[scriptable, uuid(e0737ed5-89c5-4fe3-891e-a75bf3a1bb55)]
 interface nsIDOMNavigator : nsISupports
 {
   readonly attribute DOMString             appCodeName;
   readonly attribute DOMString             appName;
   readonly attribute DOMString             appVersion;
   readonly attribute DOMString             language;
   readonly attribute nsIDOMMimeTypeArray   mimeTypes;
   readonly attribute DOMString             platform;
@@ -57,16 +57,17 @@ interface nsIDOMNavigator : nsISupports
   readonly attribute DOMString             userAgent;
   readonly attribute boolean               cookieEnabled;
   readonly attribute boolean               onLine;
   readonly attribute DOMString             buildID;
   readonly attribute DOMString             doNotTrack;
   readonly attribute nsIDOMMozPowerManager mozPower;
 
   boolean                   javaEnabled();
+  boolean                   taintEnabled();
 
   /**
    * Pulse the device's vibrator, if it has one.  If the device does not have a
    * vibrator, this function does nothing.  If the window is hidden, this
    * function does nothing.
    *
    * mozVibrate takes one argument, which specifies either how long to vibrate
    * for or gives a pattern of vibrator-on/vibrator-off timings.
--- a/dom/interfaces/geolocation/Makefile.in
+++ b/dom/interfaces/geolocation/Makefile.in
@@ -44,17 +44,16 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 XPIDL_MODULE   = dom_geolocation
 GRE_MODULE     = 1
 
 XPIDLSRCS =                                    \
             nsIDOMGeoGeolocation.idl           \
             nsIDOMGeoPosition.idl              \
-            nsIDOMGeoPositionAddress.idl       \
             nsIDOMGeoPositionCoords.idl        \
             nsIDOMGeoPositionCallback.idl      \
             nsIDOMGeoPositionError.idl         \
             nsIDOMGeoPositionErrorCallback.idl \
             nsIDOMGeoPositionOptions.idl       \
             nsIDOMNavigatorGeolocation.idl     \
             $(NULL)
 
--- a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl
@@ -32,18 +32,15 @@
  * 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"
 #include "nsIDOMGeoPositionCoords.idl"
-#include "nsIDOMGeoPositionAddress.idl"
 
-[scriptable, uuid(23E5269F-4DD7-41C4-B52A-75918694C2DE)]
+[scriptable, uuid(dd9f7e81-0f74-4fb5-b361-37019bf60c3f)]
 interface nsIDOMGeoPosition : nsISupports
 {
   readonly attribute DOMTimeStamp timestamp;
   readonly attribute nsIDOMGeoPositionCoords coords;
-  readonly attribute nsIDOMGeoPositionAddress address;
-
 };
deleted file mode 100644
--- a/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl
+++ /dev/null
@@ -1,51 +0,0 @@
-/* ***** 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 Geolocation.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Doug Turner <dougt@meer.net>  (Original Author)
- *
- * 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 ***** */
-
-
-#include "domstubs.idl"
-
-[scriptable, uuid(93abae10-7024-49eb-8e05-1931343b0ebb)]
-interface nsIDOMGeoPositionAddress : nsISupports
-{
-  readonly attribute DOMString streetNumber;
-  readonly attribute DOMString street;
-  readonly attribute DOMString premises;
-  readonly attribute DOMString city;
-  readonly attribute DOMString county;
-  readonly attribute DOMString region;
-  readonly attribute DOMString country;
-  readonly attribute DOMString postalCode;
-};
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -749,16 +749,26 @@ ContentChild::RecvDeviceMotionChanged(co
     nsCOMPtr<nsIDeviceMotionUpdate> dmu = 
         do_GetService(NS_DEVICE_MOTION_CONTRACTID);
     if (dmu)
         dmu->DeviceMotionChanged(type, x, y, z);
     return true;
 }
 
 bool
+ContentChild::RecvNeedsCalibration()
+{
+    nsCOMPtr<nsIDeviceMotionUpdate> dmu = 
+        do_GetService(NS_DEVICE_MOTION_CONTRACTID);
+    if (dmu)
+        dmu->NeedsCalibration();
+    return true;
+}
+
+bool
 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
 {
 #ifdef ANDROID
     mScreenSize = size;
 #else
     NS_RUNTIMEABORT("Message currently only expected on android");
 #endif
   return true;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -157,16 +157,18 @@ public:
     virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
 
     virtual bool RecvAddPermission(const IPC::Permission& permission);
 
     virtual bool RecvDeviceMotionChanged(const long int& type,
                                          const double& x, const double& y,
                                          const double& z);
 
+    virtual bool RecvNeedsCalibration();
+
     virtual bool RecvScreenSizeChanged(const gfxIntSize &size);
 
     virtual bool RecvFlushMemory(const nsString& reason);
 
     virtual bool RecvActivateA11y();
 
     virtual bool RecvGarbageCollect();
     virtual bool RecvCycleCollect();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1286,11 +1286,17 @@ ContentParent::OnMotionChange(nsIDeviceM
     aDeviceData->GetX(&x);
     aDeviceData->GetY(&y);
     aDeviceData->GetZ(&z);
 
     unused << SendDeviceMotionChanged(type, x, y, z);
     return NS_OK;
 }
 
+NS_IMETHODIMP
+ContentParent::NeedsCalibration() {
+    unused << SendNeedsCalibration();
+    return NS_OK;
+}
+
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -129,16 +129,17 @@ child:
     NotifyAlertsObserver(nsCString topic, nsString data);
 
     GeolocationUpdate(GeoPosition somewhere);
 
     // nsIPermissionManager messages
     AddPermission(Permission permission);
 
     DeviceMotionChanged(long type, double x, double y, double z);
+    NeedsCalibration();
 
     ScreenSizeChanged(gfxIntSize size);
 
     FlushMemory(nsString reason);
 
     GarbageCollect();
     CycleCollect();
     
--- a/dom/src/geolocation/nsGeoPosition.cpp
+++ b/dom/src/geolocation/nsGeoPosition.cpp
@@ -36,110 +36,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsGeoPosition.h"
 #include "nsDOMClassInfoID.h"
 
 ////////////////////////////////////////////////////
-// nsGeoPositionAddress
-////////////////////////////////////////////////////
-
-nsGeoPositionAddress::nsGeoPositionAddress(const nsAString &aStreetNumber,
-                                           const nsAString &aStreet,
-                                           const nsAString &aPremises,
-                                           const nsAString &aCity,
-                                           const nsAString &aCounty,
-                                           const nsAString &aRegion,
-                                           const nsAString &aCountry,
-                                           const nsAString &aPostalCode)
-    : mStreetNumber(aStreetNumber)
-    , mStreet(aStreet)
-    , mPremises(aPremises)
-    , mCity(aCity)
-    , mCounty(aCounty)
-    , mRegion(aRegion)
-    , mCountry(aCountry)
-    , mPostalCode(aPostalCode)
-{
-}
-
-nsGeoPositionAddress::~nsGeoPositionAddress()
-{
-}
-
-DOMCI_DATA(GeoPositionAddress, nsGeoPositionAddress)
-
-NS_INTERFACE_MAP_BEGIN(nsGeoPositionAddress)
-NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionAddress)
-NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionAddress)
-NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionAddress)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionAddress)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionAddress)
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetStreetNumber(nsAString & aStreetNumber)
-{
-  aStreetNumber = mStreetNumber;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetStreet(nsAString & aStreet)
-{
-  aStreet = mStreet;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetPremises(nsAString & aPremises)
-{
-  aPremises = mPremises;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetCity(nsAString & aCity)
-{
-  aCity = mCity;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetCounty(nsAString & aCounty)
-{
-  aCounty = mCounty;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetRegion(nsAString & aRegion)
-{
-  aRegion = mRegion;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetCountry(nsAString & aCountry)
-{
-  aCountry = mCountry;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeoPositionAddress::GetPostalCode(nsAString & aPostalCode)
-{
-  aPostalCode = mPostalCode;
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////
 // nsGeoPositionCoords
 ////////////////////////////////////////////////////
 nsGeoPositionCoords::nsGeoPositionCoords(double aLat, double aLong,
                                          double aAlt, double aHError,
                                          double aVError, double aHeading,
                                          double aSpeed)
   : mLat(aLat)
   , mLong(aLong)
@@ -234,21 +140,19 @@ nsGeoPosition::nsGeoPosition(double aLat
 nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
                              long long aTimestamp) :
     mTimestamp(aTimestamp),
     mCoords(aCoords)
 {
 }
 
 nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
-                             nsIDOMGeoPositionAddress *aAddress,
                              DOMTimeStamp aTimestamp) :
   mTimestamp(aTimestamp),
-  mCoords(aCoords),
-  mAddress(aAddress)
+  mCoords(aCoords)
 {
 }
 
 nsGeoPosition::~nsGeoPosition()
 {
 }
 
 DOMCI_DATA(GeoPosition, nsGeoPosition)
@@ -270,16 +174,8 @@ nsGeoPosition::GetTimestamp(DOMTimeStamp
 }
 
 NS_IMETHODIMP
 nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords)
 {
   NS_IF_ADDREF(*aCoords = mCoords);
   return NS_OK;
 }
-
-NS_IMETHODIMP
-nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress)
-{
-  NS_IF_ADDREF(*aAddress = mAddress);
-  return NS_OK;
-}
-
--- a/dom/src/geolocation/nsGeoPosition.h
+++ b/dom/src/geolocation/nsGeoPosition.h
@@ -38,53 +38,21 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsGeoPosition_h
 #define nsGeoPosition_h
 
 #include "nsAutoPtr.h"
 #include "nsIClassInfo.h"
 #include "nsDOMClassInfoID.h"
-#include "nsIDOMGeoPositionAddress.h"
 #include "nsIDOMGeoPositionCoords.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsString.h"
 
 ////////////////////////////////////////////////////
-// nsGeoPositionAddress
-////////////////////////////////////////////////////
-
-class nsGeoPositionAddress : public nsIDOMGeoPositionAddress
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMGEOPOSITIONADDRESS
-
-  nsGeoPositionAddress( const nsAString &aStreetNumber,
-                        const nsAString &aStreet,
-                        const nsAString &aPremises,
-                        const nsAString &aCity,
-                        const nsAString &aCounty,
-                        const nsAString &aRegion,
-                        const nsAString &aCountry,
-                        const nsAString &aPostalCode);
-
-    ~nsGeoPositionAddress();
-  private:
-    const nsString mStreetNumber;
-    const nsString mStreet;
-    const nsString mPremises;
-    const nsString mCity;
-    const nsString mCounty;
-    const nsString mRegion;
-    const nsString mCountry;
-    const nsString mPostalCode;
-};
-
-////////////////////////////////////////////////////
 // nsGeoPositionCoords
 ////////////////////////////////////////////////////
 
 /**
  * Simple object that holds a single point in space.
  */
 class nsGeoPositionCoords MOZ_FINAL : public nsIDOMGeoPositionCoords
 {
@@ -117,24 +85,18 @@ public:
                 double aVError, double aHeading,
                 double aSpeed, long long aTimestamp);
   
 
   nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
                 long long aTimestamp);
 
   nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
-                nsIDOMGeoPositionAddress *aAddress,
                 DOMTimeStamp aTimestamp);
 
-  void SetAddress(nsIDOMGeoPositionAddress *address) {
-    mAddress = address;
-  }
-
 private:
   ~nsGeoPosition();
   long long mTimestamp;
   nsRefPtr<nsIDOMGeoPositionCoords> mCoords;
-  nsRefPtr<nsIDOMGeoPositionAddress> mAddress;
 };
 
 #endif /* nsGeoPosition_h */
 
--- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
+++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
@@ -36,109 +36,22 @@
 
 #ifndef dom_src_geolocation_IPC_serialiser
 #define dom_src_geolocation_IPC_serialiser
 
 #include "IPC/IPCMessageUtils.h"
 #include "nsGeoPosition.h"
 #include "nsIDOMGeoPosition.h"
 
-typedef nsIDOMGeoPositionAddress  *GeoPositionAddress;
 typedef nsGeoPositionCoords       *GeoPositionCoords;
 typedef nsIDOMGeoPosition         *GeoPosition;
 
 namespace IPC {
 
 template <>
-struct ParamTraits<GeoPositionAddress>
-{
-  typedef GeoPositionAddress paramType;
-
-  // Function to serialize a geo position address
-  static void Write(Message *aMsg, const paramType& aParam)
-  {
-    bool isNull = !aParam;
-    WriteParam(aMsg, isNull);
-    // If it is null, then we are done
-    if (isNull) return;
-
-    nsString addressLine;
-
-    aParam->GetStreetNumber(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetStreet(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetPremises(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetCity(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetCounty(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetRegion(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetCountry(addressLine);
-    WriteParam(aMsg, addressLine);
-
-    aParam->GetPostalCode(addressLine);
-    WriteParam(aMsg, addressLine);
-  }
-
-  // Function to de-serialize a geoposition
-  static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
-  {
-    // Check if it is the null pointer we have transfered
-    bool isNull;
-    if (!ReadParam(aMsg, aIter, &isNull)) return false;
-
-    if (isNull) {
-      *aResult = 0;
-      return true;
-    }
-
-    // We need somewhere to store the address before we create the object
-    nsString streetNumber;
-    nsString street;
-    nsString premises;
-    nsString city;
-    nsString county;
-    nsString region;
-    nsString country;
-    nsString postalCode;
-
-    // It's not important to us where it fails, but rather if it fails
-    if (!(ReadParam(aMsg, aIter, &streetNumber) &&
-          ReadParam(aMsg, aIter, &street      ) &&
-          ReadParam(aMsg, aIter, &premises    ) &&
-          ReadParam(aMsg, aIter, &city        ) &&
-          ReadParam(aMsg, aIter, &county      ) &&
-          ReadParam(aMsg, aIter, &region      ) &&
-          ReadParam(aMsg, aIter, &country     ) &&
-          ReadParam(aMsg, aIter, &postalCode  ))) return false;
-
-    // We now have all the data
-    *aResult = new nsGeoPositionAddress(streetNumber, /* aStreetNumber */
-                                        street,       /* aStreet       */
-                                        premises,     /* aPremises     */
-                                        city,         /* aCity         */
-                                        county,       /* aCounty       */
-                                        region,       /* aRegion       */
-                                        country,      /* aCountry      */
-                                        postalCode    /* aPostalCode   */
-                                       );
-    return true;
-  }
-} ;
-
-template <>
 struct ParamTraits<GeoPositionCoords>
 {
   typedef GeoPositionCoords paramType;
 
   // Function to serialize a geoposition
   static void Write(Message *aMsg, const paramType& aParam)
   {
     bool isNull = !aParam;
@@ -230,51 +143,43 @@ struct ParamTraits<GeoPosition>
     DOMTimeStamp timeStamp;
     aParam->GetTimestamp(&timeStamp);
     WriteParam(aMsg, timeStamp);
 
     nsCOMPtr<nsIDOMGeoPositionCoords> coords;
     aParam->GetCoords(getter_AddRefs(coords));
     GeoPositionCoords simpleCoords = static_cast<GeoPositionCoords>(coords.get());
     WriteParam(aMsg, simpleCoords);
-
-    nsCOMPtr<nsIDOMGeoPositionAddress> address;
-    aParam->GetAddress(getter_AddRefs(address));
-    GeoPositionAddress simpleAddress = address.get();
-    WriteParam(aMsg, simpleAddress);
   }
 
   // Function to de-serialize a geoposition
   static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
   {
     // Check if it is the null pointer we have transfered
     bool isNull;
     if (!ReadParam(aMsg, aIter, &isNull)) return false;
 
     if (isNull) {
       *aResult = 0;
       return true;
     }
 
     DOMTimeStamp timeStamp;
     GeoPositionCoords coords = nsnull;
-    GeoPositionAddress address;
 
     // It's not important to us where it fails, but rather if it fails
     if (!(   ReadParam(aMsg, aIter, &timeStamp)
-          && ReadParam(aMsg, aIter, &coords   )
-          && ReadParam(aMsg, aIter, &address  ))) {
+          && ReadParam(aMsg, aIter, &coords   ))) {
           // note it is fine to do "delete nsnull" in case coords hasn't
-          // been allocated and we will never have a case where address
-          // gets allocated and we end here
+          // been allocated
           delete coords;
           return false;
       }
 
-    *aResult = new nsGeoPosition(coords, address, timeStamp);
+    *aResult = new nsGeoPosition(coords, timeStamp);
 
     return true;
   };
 
 };
 
 }
 
--- a/dom/system/Makefile.in
+++ b/dom/system/Makefile.in
@@ -82,16 +82,19 @@ EXTRA_COMPONENTS = \
   GPSDGeolocationProvider.manifest \
   $(NULL)
 endif
 
 EXPORTS     = \
   nsDeviceMotion.h \
   $(NULL)
 
+# We fire the nsDOMDeviceAcceleration
+LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
+
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/system/android/Makefile.in
+++ b/dom/system/android/Makefile.in
@@ -54,12 +54,13 @@ include $(topsrcdir)/ipc/chromium/chromi
 
 CPPSRCS     = \
         nsDeviceMotionSystem.cpp \
         AndroidLocationProvider.cpp \
         nsHapticFeedback.cpp \
         $(NULL)
 
 LOCAL_INCLUDES  += -I$(topsrcdir)/dom/src/geolocation \
+                     -I$(topsrcdir)/content/events/src
                      $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/system/cocoa/Makefile.in
+++ b/dom/system/cocoa/Makefile.in
@@ -44,15 +44,19 @@ include $(DEPTH)/config/autoconf.mk
 MODULE      = dom
 LIBRARY_NAME    = domsystemcocoa_s
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
+# We fire the nsDOMDeviceAcceleration
+LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
+
 include $(topsrcdir)/config/config.mk
 
 CMMSRCS     = \
+        smslib.mm \
         nsDeviceMotionSystem.mm \
         $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/system/cocoa/nsDeviceMotionSystem.mm
+++ b/dom/system/cocoa/nsDeviceMotionSystem.mm
@@ -37,171 +37,60 @@
 #include "nsDeviceMotionSystem.h"
 #include "nsIServiceManager.h"
 #include "stdlib.h"
 
 #include <sys/sysctl.h>
 #include <sys/resource.h>
 #include <sys/vm.h>
 
-#define MODEL_NAME_LENGTH 64
-static char gModelName[MODEL_NAME_LENGTH];
+#import "smslib.h"
+#define MEAN_GRAVITY 9.80665
+#define DEFAULT_SENSOR_POLL 100
 
 nsDeviceMotionSystem::nsDeviceMotionSystem()
 {
 }
 
 nsDeviceMotionSystem::~nsDeviceMotionSystem()
 {
 }
 
-// Data format returned from IOConnectMethodStructureIStructureO.
-// I am not sure what the other bits in this structure are,
-// or if there are any, but this has to be 40 bytes long or
-// the call to read fails.
-//
-// Since we make the SmsData struct larger than any members we plan to access we
-// keep track of the the size of the part of the struct we plan to access for
-// use in bounds checking.
-#define SMSDATA_PADDING_SIZE 34
-typedef struct
-{
-  PRInt16 x;
-  PRInt16 y;
-  PRInt16 z;
-  PRInt8  unknown[SMSDATA_PADDING_SIZE];
-} SmsData;
-#define SMSDATA_USED_SIZE (sizeof(SmsData) - SMSDATA_PADDING_SIZE)
-
 void
 nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure)
 {
   nsDeviceMotionSystem *self = reinterpret_cast<nsDeviceMotionSystem *>(aClosure);
   if (!self) {
     NS_ERROR("no self");
     return;
   }
-
-  size_t bufferLen = sizeof(SmsData);
-
-  void * input = malloc(bufferLen);
-  void * output = malloc(bufferLen);
-
-  if (!input || !output)
-    return;
-
-  memset(input, 0, bufferLen);
-  memset(output, 0, bufferLen);
-
-  size_t structureOutputSize = bufferLen;
-#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
-  kern_return_t result = ::IOConnectMethodStructureIStructureO(self->mSmsConnection,
-                                                               5, /* Magic number for SMCMotionSensor */
-                                                               bufferLen,
-                                                               (IOByteCount*)&structureOutputSize,
-                                                               input,
-                                                               output);
-#else
-  kern_return_t result = ::IOConnectCallStructMethod((mach_port_t)self->mSmsConnection,
-                                                     5, /* Magic number for SMCMotionSensor */
-                                                     input,
-                                                     bufferLen,
-                                                     output,
-                                                     &structureOutputSize);
-#endif
+  sms_acceleration accel;
+  smsGetData(&accel);
 
-  if ((result != kIOReturnSuccess) || (structureOutputSize < SMSDATA_USED_SIZE)) {
-    free(input);
-    free(output);
-    return;
-  }
-
-  SmsData *data = (SmsData*) output;
-
-  float xf, yf, zf;
-
-  // we want to normalize the return result from the chip to
-  // something between -1 and 1 where 0 is the balance point.
-
-  const int normalizeFactor = 250.5;
-
-  if (!strcmp(gModelName, "MacBookPro5,1")) {
-    xf = ((float)data->x) / normalizeFactor;
-    yf = (((float)data->y) / normalizeFactor) * -1;
-    zf = ((float)data->z) / normalizeFactor;
-  }
-  else if (!strcmp(gModelName, "MacBookPro5,3")) {
-    xf = ((float)data->y) / normalizeFactor;
-    yf = (((float)data->x) / normalizeFactor) * -1;
-    zf = (((float)data->z) / normalizeFactor) * -1;
-  }
-  else
-  {
-    xf = (((float)data->x) / normalizeFactor) * -1;
-    yf = ((float)data->y) / normalizeFactor;
-    zf = ((float)data->z) / normalizeFactor;
-  }
-
-  free(input);
-  free(output);
-
-  self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, xf, yf, zf );
+  self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION,
+			    accel.x * MEAN_GRAVITY,
+			    accel.y * MEAN_GRAVITY,
+			    accel.z * MEAN_GRAVITY);
 }
 
 void nsDeviceMotionSystem::Startup()
 {
-  // we can fail, and that just means the caller will not see any changes.
-
-  mach_port_t port;
-  kern_return_t result = ::IOMasterPort(MACH_PORT_NULL, &port);
-  if (result != kIOReturnSuccess)
-    return;
-
-  CFMutableDictionaryRef  dict = ::IOServiceMatching("SMCMotionSensor");
-  if (!dict)
-    return;
-
-  io_iterator_t iter;
-  result = ::IOServiceGetMatchingServices(port, dict, &iter);
-  if (result != kIOReturnSuccess)
-    return;
-
-  io_object_t device = ::IOIteratorNext(iter);
-
-  ::IOObjectRelease(iter);
-
-  if (!device)
-    return;
-
-  result = ::IOServiceOpen(device, mach_task_self(), 0, &mSmsConnection);
-  ::IOObjectRelease(device);
-
-  if (result != kIOReturnSuccess)
-    return;
-
-  mach_port_deallocate(mach_task_self(), port);
-
-  /* get the version of the hardware we are running on. */
-  int mib[2];
-  size_t len = MODEL_NAME_LENGTH;
-  mib[0] = CTL_HW;
-  mib[1] = HW_MODEL;
-  sysctl(mib, 2, gModelName, &len, NULL, 0);
+  smsStartup(nil, nil);
+  smsLoadCalibration();
 
   mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1");
   if (mUpdateTimer)
     mUpdateTimer->InitWithFuncCallback(UpdateHandler,
                                        this,
-                                       mUpdateInterval,
+                                       DEFAULT_SENSOR_POLL,
                                        nsITimer::TYPE_REPEATING_SLACK);
 }
 
 void nsDeviceMotionSystem::Shutdown()
 {
-  if (mSmsConnection)
-    ::IOServiceClose(mSmsConnection);
-
   if (mUpdateTimer) {
     mUpdateTimer->Cancel();
     mUpdateTimer = nsnull;
   }
+
+  smsShutdown();
 }
 
new file mode 100644
--- /dev/null
+++ b/dom/system/cocoa/smslib.h
@@ -0,0 +1,159 @@
+/*
+ * smslib.h
+ *
+ * SMSLib Sudden Motion Sensor Access Library
+ * Copyright (c) 2010 Suitable Systems
+ * All rights reserved.
+ * 
+ * Developed by: Daniel Griscom
+ *               Suitable Systems
+ *               http://www.suitable.com
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal with the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimers.
+ * 
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimers in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * - Neither the names of Suitable Systems nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this Software without specific prior written permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
+ *
+ * For more information about SMSLib, see
+ *		<http://www.suitable.com/tools/smslib.html>
+ * or contact
+ *		Daniel Griscom
+ *		Suitable Systems
+ *		1 Centre Street, Suite 204
+ *		Wakefield, MA 01880
+ *		(781) 665-0053
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#define SMSLIB_VERSION "1.8"
+
+#pragma mark Structure definitions
+
+// Structure for specifying a 3-axis acceleration. 0.0 means "zero gravities",
+// 1.0 means "one gravity".
+typedef struct sms_acceleration {
+	float x;		// Right-left acceleration (positive is rightwards)
+	float y;		// Front-rear acceleration (positive is rearwards)
+	float z;		// Up-down acceleration (positive is upwards)
+} sms_acceleration;
+
+// Structure for specifying a calibration.
+typedef struct sms_calibration {
+	float zeros[3];	// Zero points for three axes (X, Y, Z)
+	float onegs[3];	// One gravity values for three axes
+} sms_calibration;
+
+#pragma mark Return value definitions
+
+// These are the return values for accelStartup(), giving the
+// various stages where the most successful attempt at accessing
+// the accelerometer failed. The higher the value, the further along the
+// software progressed before failing. The options are:
+//	- Didn't match model name
+#define SMS_FAIL_MODEL			(-7)
+//	- Failure getting dictionary matching desired services
+#define SMS_FAIL_DICTIONARY		(-6)
+//	- Failure getting list of services
+#define SMS_FAIL_LIST_SERVICES	(-5)
+//	- Failure if list of services is empty. The process generally fails
+//		here if run on a machine without a Sudden Motion Sensor.
+#define SMS_FAIL_NO_SERVICES	(-4)
+//	- Failure if error opening device.
+#define SMS_FAIL_OPENING		(-3)
+//	- Failure if opened, but didn't get a connection
+#define SMS_FAIL_CONNECTION		(-2)
+//	- Failure if couldn't access connction using given function and size. This
+//		is where the process would probably fail with a change in Apple's API.
+//		Driver problems often also cause failures here.
+#define SMS_FAIL_ACCESS			(-1)
+//	- Success!
+#define SMS_SUCCESS				(0)
+
+#pragma mark Function declarations
+
+// This starts up the accelerometer code, trying each possible sensor
+// specification. Note that for logging purposes it
+// takes an object and a selector; the object's selector is then invoked
+// with a single NSString as argument giving progress messages. Example
+// logging method:
+//		- (void)logMessage: (NSString *)theString
+// which would be used in accelStartup's invocation thusly:
+//		result = accelStartup(self, @selector(logMessage:));
+// If the object is nil, then no logging is done. Sets calibation from built-in
+// value table. Returns ACCEL_SUCCESS for success, and other (negative)
+// values for various failures (returns value indicating result of
+// most successful trial).
+int smsStartup(id logObject, SEL logSelector);
+
+// This starts up the library in debug mode, ignoring the actual hardware.
+// Returned data is in the form of 1Hz sine waves, with the X, Y and Z
+// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5);
+// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0,
+// Z axes centered on 1 (calibrated) or 256 (uncalibrated). 
+// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS.
+int smsDebugStartup(id logObject, SEL logSelector);
+
+// Returns the current calibration values.
+void smsGetCalibration(sms_calibration *calibrationRecord);
+
+// Sets the calibration, but does NOT store it as a preference. If the argument
+// is nil then the current calibration is set from the built-in value table.
+void smsSetCalibration(sms_calibration *calibrationRecord);
+
+// Stores the current calibration values as a stored preference.
+void smsStoreCalibration(void);
+
+// Loads the stored preference values into the current calibration.
+// Returns YES if successful.
+BOOL smsLoadCalibration(void);
+
+// Deletes any stored calibration, and then takes the current calibration values
+// from the built-in value table.
+void smsDeleteCalibration(void);
+
+// Fills in the accel record with calibrated acceleration data. Takes
+// 1-2ms to return a value. Returns 0 if success, error number if failure.
+int smsGetData(sms_acceleration *accel);
+
+// Fills in the accel record with uncalibrated acceleration data.
+// Returns 0 if success, error number if failure.
+int smsGetUncalibratedData(sms_acceleration *accel);
+
+// Returns the length of a raw block of data for the current type of sensor.
+int smsGetBufferLength(void);
+
+// Takes a pointer to accelGetRawLength() bytes; sets those bytes
+// to return value from sensor. Make darn sure the buffer length is right!
+void smsGetBufferData(char *buffer);
+
+// This returns an NSString describing the current calibration in
+// human-readable form. Also include a description of the machine.
+NSString *smsGetCalibrationDescription(void);
+
+// Shuts down the accelerometer.
+void smsShutdown(void);
+
new file mode 100644
--- /dev/null
+++ b/dom/system/cocoa/smslib.mm
@@ -0,0 +1,937 @@
+/*
+ * smslib.m
+ * 
+ * SMSLib Sudden Motion Sensor Access Library
+ * Copyright (c) 2010 Suitable Systems
+ * All rights reserved.
+ * 
+ * Developed by: Daniel Griscom
+ *               Suitable Systems
+ *               http://www.suitable.com
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal with the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimers.
+ * 
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimers in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * - Neither the names of Suitable Systems nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this Software without specific prior written permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
+ *
+ * For more information about SMSLib, see
+ *		<http://www.suitable.com/tools/smslib.html>
+ * or contact
+ *		Daniel Griscom
+ *		Suitable Systems
+ *		1 Centre Street, Suite 204
+ *		Wakefield, MA 01880
+ *		(781) 665-0053
+ *
+ */
+
+#import <IOKit/IOKitLib.h>
+#import <sys/sysctl.h>
+#import <math.h>
+#import "smslib.h"
+
+#pragma mark Internal structures
+
+// Represents a single axis of a type of sensor.
+typedef struct axisStruct {
+	int enabled;				// Non-zero if axis is valid in this sensor
+	int index;					// Location in struct of first byte
+	int size;					// Number of bytes
+	float zerog;				// Value meaning "zero g"
+	float oneg;					// Change in value meaning "increase of one g"
+								// (can be negative if axis sensor reversed)
+} axisStruct;
+
+// Represents the configuration of a type of sensor.
+typedef struct sensorSpec {
+	char *model;				// Prefix of model to be tested
+	char *name;					// Name of device to be read
+	unsigned int function;		// Kernel function index
+	int recordSize;				// Size of record to be sent/received
+	axisStruct axes[3];			// Description of three axes (X, Y, Z)
+} sensorSpec;
+	
+// Configuration of all known types of sensors. The configurations are
+// tried in order until one succeeds in returning data.
+// All default values are set here, but each axis' zerog and oneg values 
+// may be changed to saved (calibrated) values.
+//
+// These values came from SeisMaCalibrate calibration reports. In general I've
+// found the following:
+//	- All Intel-based SMSs have 250 counts per g, centered on 0, but the signs
+//		are different (and in one case two axes are swapped)
+//	- PowerBooks and iBooks all have sensors centered on 0, and reading
+//		50-53 steps per gravity (but with differing polarities!)
+//	- PowerBooks and iBooks of the same model all have the same axis polarities
+//	- PowerBook and iBook access methods are model- and OS version-specific
+//
+// So, the sequence of tests is:
+//	- Try model-specific access methods. Note that the test is for a match to the
+//		beginning of the model name, e.g. the record with model name "MacBook"
+//		matches computer models "MacBookPro1,2" and "MacBook1,1" (and ""
+//		matches any model).
+//	- If no model-specific record's access fails, then try each model-independent
+//		access method in order, stopping when one works.
+static const sensorSpec sensors[] = {
+	// ****** Model-dependent methods ******
+	// The PowerBook5,6 is one of the G4 models that seems to lose
+	// SMS access until the next reboot.
+	{"PowerBook5,6", "IOI2CMotionSensor", 21, 60, {
+			{1, 0, 1, 0,  51.5},
+			{1, 1, 1, 0, -51.5},
+			{1, 2, 1, 0, -51.5}
+		}
+	},
+	// The PowerBook5,7 is one of the G4 models that seems to lose
+	// SMS access until the next reboot.
+	{"PowerBook5,7", "IOI2CMotionSensor", 21, 60, {
+			{1, 0, 1, 0,  51.5},
+			{1, 1, 1, 0,  51.5},
+			{1, 2, 1, 0,  51.5}
+		}
+	},
+	// Access seems to be reliable on the PowerBook5,8
+	{"PowerBook5,8", "PMUMotionSensor", 21, 60, {
+			{1, 0, 1, 0, -51.5},
+			{1, 1, 1, 0,  51.5},
+			{1, 2, 1, 0, -51.5}
+		}
+	},
+	// Access seems to be reliable on the PowerBook5,9
+	{"PowerBook5,9", "PMUMotionSensor", 21, 60, {
+			{1, 0, 1, 0,  51.5},
+			{1, 1, 1, 0, -51.5},
+			{1, 2, 1, 0, -51.5}
+		}
+	},
+	// The PowerBook6,7 is one of the G4 models that seems to lose
+	// SMS access until the next reboot.
+	{"PowerBook6,7", "IOI2CMotionSensor", 21, 60, {
+			{1, 0, 1, 0,  51.5},
+			{1, 1, 1, 0,  51.5},
+			{1, 2, 1, 0,  51.5}
+		}
+	},
+	// The PowerBook6,8 is one of the G4 models that seems to lose
+	// SMS access until the next reboot.
+	{"PowerBook6,8", "IOI2CMotionSensor", 21, 60, {
+			{1, 0, 1, 0,  51.5},
+			{1, 1, 1, 0,  51.5},
+			{1, 2, 1, 0,  51.5}
+		}
+	},
+	// MacBook Pro Core 2 Duo 17". Note the reversed Y and Z axes.
+	{"MacBookPro2,1", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0,  251},
+			{1, 2, 2, 0, -251},
+			{1, 4, 2, 0, -251}
+		}
+	},
+	// MacBook Pro Core 2 Duo 15" AND 17" with LED backlight, introduced June '07.
+	// NOTE! The 17" machines have the signs of their X and Y axes reversed
+	// from this calibration, but there's no clear way to discriminate between
+	// the two machines.
+	{"MacBookPro3,1", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, -251},
+			{1, 2, 2, 0,  251},
+			{1, 4, 2, 0, -251}
+		}
+	},
+	// ... specs?
+	{"MacBook5,2", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, -251},
+			{1, 2, 2, 0,  251},
+			{1, 4, 2, 0, -251}
+		}
+	},
+	// ... specs?
+	{"MacBookPro5,1", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, -251},
+			{1, 2, 2, 0, -251},
+			{1, 4, 2, 0,  251}
+		}
+	},
+	// ... specs?
+	{"MacBookPro5,2", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, -251},
+			{1, 2, 2, 0, -251},
+			{1, 4, 2, 0,  251}
+		}
+	},
+	// This is speculative, based on a single user's report. Looks like the X and Y axes
+	// are swapped. This is true for no other known Appple laptop.
+	{"MacBookPro5,3", "SMCMotionSensor", 5, 40, {
+			{1, 2, 2, 0, -251},
+			{1, 0, 2, 0, -251},
+			{1, 4, 2, 0, -251}
+		}
+	},
+	// ... specs?
+	{"MacBookPro5,4", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, -251},
+			{1, 2, 2, 0, -251},
+			{1, 4, 2, 0,  251}
+		}
+	},
+	// ****** Model-independent methods ******
+	// Seen once with PowerBook6,8 under system 10.3.9; I suspect
+	// other G4-based 10.3.* systems might use this
+	{"", "IOI2CMotionSensor", 24, 60, {
+			{1, 0, 1, 0, 51.5},
+			{1, 1, 1, 0, 51.5},
+			{1, 2, 1, 0, 51.5}
+		}
+	},
+	// PowerBook5,6 , PowerBook5,7 , PowerBook6,7 , PowerBook6,8
+	// under OS X 10.4.*
+	{"", "IOI2CMotionSensor", 21, 60, {
+			{1, 0, 1, 0, 51.5},
+			{1, 1, 1, 0, 51.5},
+			{1, 2, 1, 0, 51.5}
+		}
+	},
+	// PowerBook5,8 , PowerBook5,9 under OS X 10.4.*
+	{"", "PMUMotionSensor", 21, 60, {
+			// Each has two out of three gains negative, but it's different
+			// for the different models. So, this will be right in two out
+			// of three axis for either model.
+			{1, 0, 1,  0, -51.5},
+			{1, 1, 1, -6, -51.5},
+			{1, 2, 1,  0, -51.5}
+		}
+	},
+	// All MacBook, MacBookPro models. Hardware (at least on early MacBookPro 15")
+	// is Kionix KXM52-1050 three-axis accelerometer chip. Data is at
+	// http://kionix.com/Product-Index/product-index.htm. Specific MB and MBP models
+	// that use this are: 
+	//		MacBook1,1
+	//		MacBook2,1
+	//		MacBook3,1
+	//		MacBook4,1
+	//		MacBook5,1
+	//		MacBook6,1
+	//		MacBookAir1,1
+	//		MacBookPro1,1
+	//		MacBookPro1,2
+	//		MacBookPro4,1
+	//		MacBookPro5,5
+	{"", "SMCMotionSensor", 5, 40, {
+			{1, 0, 2, 0, 251},
+			{1, 2, 2, 0, 251},
+			{1, 4, 2, 0, 251}
+		}
+	}
+};
+
+#define SENSOR_COUNT (sizeof(sensors)/sizeof(sensorSpec))
+
+#pragma mark Internal prototypes
+
+static int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector);
+static float getAxis(int which, int calibrated);
+static int signExtend(int value, int size);
+static NSString *getModelName(void);
+static NSString *getOSVersion(void);
+static BOOL loadCalibration(void);
+static void storeCalibration(void);
+static void defaultCalibration(void);
+static void deleteCalibration(void);
+static int prefIntRead(NSString *prefName, BOOL *success);
+static void prefIntWrite(NSString *prefName, int prefValue);
+static float prefFloatRead(NSString *prefName, BOOL *success);
+static void prefFloatWrite(NSString *prefName, float prefValue);
+static void prefDelete(NSString *prefName);
+static void prefSynchronize(void);
+// static long getMicroseconds(void);
+float fakeData(NSTimeInterval time);
+
+#pragma mark Static variables
+
+static int debugging = NO;		// True if debugging (synthetic data)
+static io_connect_t connection;	// Connection for reading accel values
+static int running = NO;		// True if we successfully started
+static int sensorNum = 0;		// The current index into sensors[]
+static char *serviceName;		// The name of the current service
+static char *iRecord, *oRecord;	// Pointers to read/write records for sensor
+static int recordSize;			// Size of read/write records
+static unsigned int function;	// Which kernel function should be used
+static float zeros[3];			// X, Y and Z zero calibration values
+static float onegs[3];			// X, Y and Z one-g calibration values
+
+#pragma mark Defines
+
+// Pattern for building axis letter from axis number
+#define INT_TO_AXIS(a) (a == 0 ? @"X" : a == 1 ? @"Y" : @"Z")
+// Name of configuration for given axis' zero (axis specified by integer)
+#define ZERO_NAME(a) [NSString stringWithFormat:@"%@-Axis-Zero", INT_TO_AXIS(a)]
+// Name of configuration for given axis' oneg (axis specified by integer)
+#define ONEG_NAME(a) [NSString stringWithFormat:@"%@-Axis-One-g", INT_TO_AXIS(a)]
+// Name of "Is calibrated" preference
+#define CALIBRATED_NAME (@"Calibrated")
+// Application domain for SeisMac library
+#define APP_ID ((CFStringRef)@"com.suitable.SeisMacLib")
+
+// These #defines make the accelStartup code a LOT easier to read.
+#define LOG(message) \
+	if (logObject) { \
+		[logObject performSelector:logSelector withObject:message]; \
+	}
+#define LOG_ARG(format, var1) \
+	if (logObject) { \
+		[logObject performSelector:logSelector \
+			withObject:[NSString stringWithFormat:format, var1]]; \
+	}
+#define LOG_2ARG(format, var1, var2) \
+	if (logObject) { \
+		[logObject performSelector:logSelector \
+			withObject:[NSString stringWithFormat:format, var1, var2]]; \
+	}
+#define LOG_3ARG(format, var1, var2, var3) \
+	if (logObject) { \
+		[logObject performSelector:logSelector \
+			withObject:[NSString stringWithFormat:format, var1, var2, var3]]; \
+	}
+
+#pragma mark Function definitions
+
+// This starts up the accelerometer code, trying each possible sensor
+// specification. Note that for logging purposes it
+// takes an object and a selector; the object's selector is then invoked
+// with a single NSString as argument giving progress messages. Example
+// logging method:
+//		- (void)logMessage: (NSString *)theString
+// which would be used in accelStartup's invocation thusly:
+//		result = accelStartup(self, @selector(logMessage:));
+// If the object is nil, then no logging is done. Sets calibation from built-in
+// value table. Returns ACCEL_SUCCESS for success, and other (negative)
+// values for various failures (returns value indicating result of
+// most successful trial).
+int smsStartup(id logObject, SEL logSelector) {
+	io_iterator_t iterator;
+	io_object_t device;
+	kern_return_t result;
+	sms_acceleration accel;
+	int failure_result = SMS_FAIL_MODEL;
+		
+	running = NO;
+	debugging = NO;
+	
+	NSString *modelName = getModelName();
+	
+	LOG_ARG(@"Machine model: %@\n", modelName);
+	LOG_ARG(@"OS X version: %@\n", getOSVersion());
+	LOG_ARG(@"Accelerometer library version: %s\n", SMSLIB_VERSION);
+		
+	for (sensorNum = 0; sensorNum < SENSOR_COUNT; sensorNum++) {
+		
+		// Set up all specs for this type of sensor
+		serviceName = sensors[sensorNum].name;
+		recordSize = sensors[sensorNum].recordSize;
+		function = sensors[sensorNum].function;
+		
+		LOG_3ARG(@"Trying service \"%s\" with selector %d and %d byte record:\n",
+				serviceName, function, recordSize);
+		
+		NSString *targetName = [NSString stringWithCString:sensors[sensorNum].model
+												  encoding:NSMacOSRomanStringEncoding];
+		LOG_ARG(@"    Comparing model name to target \"%@\": ", targetName);
+		if ([targetName length] == 0 || [modelName hasPrefix:targetName]) {
+			LOG(@"success.\n");
+		} else {
+			LOG(@"failure.\n");
+			// Don't need to increment failure_result.
+			continue;
+		}
+		
+		LOG(@"    Fetching dictionary for service: ");
+		CFMutableDictionaryRef dict = IOServiceMatching(serviceName);
+		
+		if (dict) {
+			LOG(@"success.\n");
+		} else {
+			LOG(@"failure.\n");
+			if (failure_result < SMS_FAIL_DICTIONARY) {
+				failure_result = SMS_FAIL_DICTIONARY;
+			}
+			continue;
+		}
+		
+		LOG(@"    Getting list of matching services: ");
+		result = IOServiceGetMatchingServices(kIOMasterPortDefault, 
+										 dict, 
+										 &iterator);
+		
+		if (result == KERN_SUCCESS) {
+			LOG(@"success.\n");
+		} else {
+			LOG_ARG(@"failure, with return value 0x%x.\n", result);
+			if (failure_result < SMS_FAIL_LIST_SERVICES) {
+				failure_result = SMS_FAIL_LIST_SERVICES;
+			}
+			continue;
+		}
+		
+		LOG(@"    Getting first device in list: ");
+		device = IOIteratorNext(iterator);	
+		
+		if (device == 0) {
+			LOG(@"failure.\n");
+			if (failure_result < SMS_FAIL_NO_SERVICES) {
+				failure_result = SMS_FAIL_NO_SERVICES;
+			}
+			continue;
+		} else {
+			LOG(@"success.\n");
+			LOG(@"    Opening device: ");
+		}
+		
+		result = IOServiceOpen(device, mach_task_self(), 0, &connection);
+		
+		if (result != KERN_SUCCESS) {
+			LOG_ARG(@"failure, with return value 0x%x.\n", result);
+			IOObjectRelease(device);
+			if (failure_result < SMS_FAIL_OPENING) {
+				failure_result = SMS_FAIL_OPENING;
+			}
+			continue;
+		} else if (connection == 0) {
+			LOG_ARG(@"'success', but didn't get a connection.\n", result);
+			IOObjectRelease(device);
+			if (failure_result < SMS_FAIL_CONNECTION) {
+				failure_result = SMS_FAIL_CONNECTION;
+			}
+			continue;
+		} else {
+			IOObjectRelease(device);
+			LOG(@"success.\n");
+		}
+		LOG(@"    Testing device.\n");
+		
+		defaultCalibration();
+		
+		iRecord = (char*) malloc(recordSize);
+		oRecord = (char*) malloc(recordSize);
+		
+		running = YES;
+		result = getData(&accel, true, logObject, logSelector);
+		running = NO;
+		
+		if (result) {
+			LOG_ARG(@"    Failure testing device, with result 0x%x.\n", result);
+			free(iRecord);
+			iRecord = 0;
+			free(oRecord);
+			oRecord = 0;
+			if (failure_result < SMS_FAIL_ACCESS) {
+				failure_result = SMS_FAIL_ACCESS;
+			}
+			continue;
+		} else {
+			LOG(@"    Success testing device!\n");
+			running = YES;
+			return SMS_SUCCESS;
+		}
+	}
+	return failure_result;
+}
+
+// This starts up the library in debug mode, ignoring the actual hardware.
+// Returned data is in the form of 1Hz sine waves, with the X, Y and Z
+// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5);
+// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0,
+// Z axes centered on 1 (calibrated) or 256 (uncalibrated). 
+// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS.
+int smsDebugStartup(id logObject, SEL logSelector) {
+	LOG(@"Starting up in debug mode\n");
+	debugging = YES;
+	return SMS_SUCCESS;
+}
+
+// Returns the current calibration values.
+void smsGetCalibration(sms_calibration *calibrationRecord) {
+	int x;
+	
+	for (x = 0; x < 3; x++) {
+		calibrationRecord->zeros[x] = (debugging ? 0 : zeros[x]);
+		calibrationRecord->onegs[x] = (debugging ? 256 : onegs[x]);
+	}
+}
+
+// Sets the calibration, but does NOT store it as a preference. If the argument
+// is nil then the current calibration is set from the built-in value table.
+void smsSetCalibration(sms_calibration *calibrationRecord) {
+	int x;
+	
+	if (!debugging) {
+		if (calibrationRecord) {
+			for (x = 0; x < 3; x++) {
+				zeros[x] = calibrationRecord->zeros[x];
+				onegs[x] = calibrationRecord->onegs[x];
+			}
+		} else {
+			defaultCalibration();
+		}
+	}
+}
+
+// Stores the current calibration values as a stored preference.
+void smsStoreCalibration(void) {
+	if (!debugging)
+		storeCalibration();
+}
+
+// Loads the stored preference values into the current calibration.
+// Returns YES if successful.
+BOOL smsLoadCalibration(void) {
+	if (debugging) {
+		return YES;
+	} else if (loadCalibration()) {
+		return YES;
+	} else {
+		defaultCalibration();
+		return NO;
+	}
+}
+
+// Deletes any stored calibration, and then takes the current calibration values
+// from the built-in value table.
+void smsDeleteCalibration(void) {
+	if (!debugging) {
+		deleteCalibration();
+		defaultCalibration();
+	}
+}
+
+// Fills in the accel record with calibrated acceleration data. Takes
+// 1-2ms to return a value. Returns 0 if success, error number if failure.
+int smsGetData(sms_acceleration *accel) {
+	NSTimeInterval time;
+	if (debugging) {
+		usleep(1500);						// Usually takes 1-2 milliseconds
+		time = [NSDate timeIntervalSinceReferenceDate];
+		accel->x = fakeData(time)/5;
+		accel->y = fakeData(time - 1)/5;
+		accel->z = fakeData(time - 2)/5 + 1.0;
+		return true;
+	} else {
+		return getData(accel, true, nil, nil);
+	}
+}
+
+// Fills in the accel record with uncalibrated acceleration data.
+// Returns 0 if success, error number if failure.
+int smsGetUncalibratedData(sms_acceleration *accel) {
+	NSTimeInterval time;
+	if (debugging) {
+		usleep(1500);						// Usually takes 1-2 milliseconds
+		time = [NSDate timeIntervalSinceReferenceDate];
+		accel->x = fakeData(time) * 256 / 5;
+		accel->y = fakeData(time - 1) * 256 / 5;
+		accel->z = fakeData(time - 2) * 256 / 5 + 256;
+		return true;
+	} else {
+		return getData(accel, false, nil, nil);
+	}
+}
+
+// Returns the length of a raw block of data for the current type of sensor.
+int smsGetBufferLength(void) {
+	if (debugging) {
+		return 0;
+	} else if (running) {
+		return sensors[sensorNum].recordSize;
+	} else {
+		return 0;
+	}
+}
+
+// Takes a pointer to accelGetRawLength() bytes; sets those bytes
+// to return value from sensor. Make darn sure the buffer length is right!
+void smsGetBufferData(char *buffer) {
+	IOItemCount iSize = recordSize;
+	IOByteCount oSize = recordSize;
+	kern_return_t result;
+
+	if (debugging || running == NO) {
+		return;
+	}
+
+	memset(iRecord, 1, iSize);
+	memset(buffer, 0, oSize);
+#if __MAC_OS_X_VERSION_MIN_REQUIRED  >= 1050
+	const size_t InStructSize = recordSize;
+	size_t OutStructSize = recordSize;
+	result = IOConnectCallStructMethod(connection,
+						function,				// magic kernel function number
+						(const void *)iRecord,
+						InStructSize,
+						(void *)buffer,
+						&OutStructSize
+					);
+#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
+	result = IOConnectMethodStructureIStructureO(connection,
+						function,				// magic kernel function number
+						iSize,
+						&oSize,
+						iRecord,
+						buffer
+					);
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
+	
+	if (result != KERN_SUCCESS) {
+		running = NO;
+	}
+}
+
+// This returns an NSString describing the current calibration in
+// human-readable form. Also include a description of the machine.
+NSString *smsGetCalibrationDescription(void) {
+	BOOL success;
+	NSMutableString *s = [[NSMutableString alloc] init];
+	
+	if (debugging) {
+		[s release];
+		return @"Debugging!";
+	}
+	
+	[s appendString:@"---- SeisMac Calibration Record ----\n \n"];
+	[s appendFormat:@"Machine model: %@\n", 
+		getModelName()];
+	[s appendFormat:@"OS X build: %@\n", 
+		getOSVersion()];
+	[s appendFormat:@"SeisMacLib version %s, record %d\n \n", 
+		SMSLIB_VERSION, sensorNum];
+	[s appendFormat:@"Using service \"%s\", function index %d, size %d\n \n",
+		serviceName, function, recordSize];
+	if (prefIntRead(CALIBRATED_NAME, &success) && success) {
+		[s appendString:@"Calibration values (from calibration):\n"];
+	} else {
+		[s appendString:@"Calibration values (from defaults):\n"];
+	}
+	[s appendFormat:@"    X-Axis-Zero  = %.2f\n", zeros[0]];
+	[s appendFormat:@"    X-Axis-One-g = %.2f\n", onegs[0]];
+	[s appendFormat:@"    Y-Axis-Zero  = %.2f\n", zeros[1]];
+	[s appendFormat:@"    Y-Axis-One-g = %.2f\n", onegs[1]];
+	[s appendFormat:@"    Z-Axis-Zero  = %.2f\n", zeros[2]];
+	[s appendFormat:@"    Z-Axis-One-g = %.2f\n \n", onegs[2]];
+	[s appendString:@"---- End Record ----\n"];
+	return s;
+}
+
+// Shuts down the accelerometer.
+void smsShutdown(void) {
+	if (!debugging) {
+		running = NO;
+		if (iRecord) free(iRecord);
+		if (oRecord) free(oRecord);
+		IOServiceClose(connection);
+	}
+}
+
+#pragma mark Internal functions
+
+// Loads the current calibration from the stored preferences.
+// Returns true iff successful.
+BOOL loadCalibration(void) {
+	BOOL thisSuccess, allSuccess;
+	int x;
+	
+	prefSynchronize();
+	
+	if (prefIntRead(CALIBRATED_NAME, &thisSuccess) && thisSuccess) {
+		// Calibrated. Set all values from saved values.
+		allSuccess = YES;
+		for (x = 0; x < 3; x++) {
+			zeros[x] = prefFloatRead(ZERO_NAME(x), &thisSuccess);
+			allSuccess &= thisSuccess;
+			onegs[x] = prefFloatRead(ONEG_NAME(x), &thisSuccess);
+			allSuccess &= thisSuccess;
+		}
+		return allSuccess;
+	}
+	
+	return NO;
+}
+
+// Stores the current calibration into the stored preferences.
+static void storeCalibration(void) {
+	int x;
+	prefIntWrite(CALIBRATED_NAME, 1);
+	for (x = 0; x < 3; x++) {
+		prefFloatWrite(ZERO_NAME(x), zeros[x]);
+		prefFloatWrite(ONEG_NAME(x), onegs[x]);
+	}	
+	prefSynchronize();
+}
+
+
+// Sets the calibration to its default values.
+void defaultCalibration(void) {
+	int x;
+	for (x = 0; x < 3; x++) {
+		zeros[x] = sensors[sensorNum].axes[x].zerog;
+		onegs[x] = sensors[sensorNum].axes[x].oneg;
+	}
+}
+
+// Deletes the stored preferences.
+static void deleteCalibration(void) {
+	int x;
+	
+	prefDelete(CALIBRATED_NAME);
+	for (x = 0; x < 3; x++) {
+		prefDelete(ZERO_NAME(x));
+		prefDelete(ONEG_NAME(x));
+	}
+	prefSynchronize();
+}
+
+// Read a named floating point value from the stored preferences. Sets
+// the success boolean based on, you guessed it, whether it succeeds.
+static float prefFloatRead(NSString *prefName, BOOL *success) {
+	float result = 0.0f;
+	
+	CFPropertyListRef ref = CFPreferencesCopyAppValue((CFStringRef)prefName, 
+													   APP_ID);
+	// If there isn't such a preference, fail
+	if (ref == NULL) {
+		*success = NO;
+		return result;
+	}
+	CFTypeID typeID = CFGetTypeID(ref);
+	// Is it a number?
+	if (typeID == CFNumberGetTypeID()) {
+		// Is it a floating point number?
+		if (CFNumberIsFloatType((CFNumberRef)ref)) {
+			// Yup: grab it.
+			*success = CFNumberGetValue((__CFNumber*)ref, kCFNumberFloat32Type, &result);
+		} else {
+			// Nope: grab as an integer, and convert to a float.
+			long num;
+			if (CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &num)) {
+				result = num;
+				*success = YES;
+			} else {
+				*success = NO;
+			}
+		}
+	// Or is it a string (e.g. set by the command line "defaults" command)?
+	} else if (typeID == CFStringGetTypeID()) {
+		result = (float)CFStringGetDoubleValue((CFStringRef)ref);
+		*success = YES;
+	} else {
+		// Can't convert to a number: fail.
+		*success = NO;
+	}
+	CFRelease(ref);
+	return result;
+}
+
+// Writes a named floating point value to the stored preferences.
+static void prefFloatWrite(NSString *prefName, float prefValue) {
+	CFNumberRef cfFloat = CFNumberCreate(kCFAllocatorDefault,
+										 kCFNumberFloatType,
+										 &prefValue);
+	CFPreferencesSetAppValue((CFStringRef)prefName,
+							 cfFloat,
+							 APP_ID);
+	CFRelease(cfFloat);
+}
+
+// Reads a named integer value from the stored preferences.
+static int prefIntRead(NSString *prefName, BOOL *success) {
+	Boolean internalSuccess;
+	CFIndex result = CFPreferencesGetAppIntegerValue((CFStringRef)prefName,
+													 APP_ID, 
+													 &internalSuccess);
+	*success = internalSuccess;
+	
+	return result;
+}
+
+// Writes a named integer value to the stored preferences.
+static void prefIntWrite(NSString *prefName, int prefValue) {
+	CFPreferencesSetAppValue((CFStringRef)prefName,
+							 (CFNumberRef)[NSNumber numberWithInt:prefValue],
+							 APP_ID);
+}
+
+// Deletes the named preference values.
+static void prefDelete(NSString *prefName) {
+		CFPreferencesSetAppValue((CFStringRef)prefName,
+								 NULL,
+								 APP_ID);
+}
+
+// Synchronizes the local preferences with the stored preferences.
+static void prefSynchronize(void) {
+	CFPreferencesAppSynchronize(APP_ID);
+}
+
+// Internal version of accelGetData, with logging
+int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector) {
+	IOItemCount iSize = recordSize;
+	IOByteCount oSize = recordSize;
+	kern_return_t result;
+	
+	if (running == NO) {
+		return -1;
+	}
+	
+	memset(iRecord, 1, iSize);
+	memset(oRecord, 0, oSize);
+	
+	LOG_2ARG(@"    Querying device: ", 
+			 sensors[sensorNum].function, sensors[sensorNum].recordSize);
+	
+#if __MAC_OS_X_VERSION_MIN_REQUIRED  >= 1050
+	const size_t InStructSize = recordSize;
+	size_t OutStructSize = recordSize;
+	result = IOConnectCallStructMethod(connection,
+						function,				// magic kernel function number
+						(const void *)iRecord,
+						InStructSize,
+						(void *)oRecord,
+						&OutStructSize
+					);
+#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
+	result = IOConnectMethodStructureIStructureO(connection,
+						function,				// magic kernel function number
+						iSize,
+						&oSize,
+						iRecord,
+						oRecord
+					);
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
+
+	if (result != KERN_SUCCESS) {
+		LOG(@"failed.\n");
+		running = NO;
+		return result;
+	} else {
+		LOG(@"succeeded.\n");
+		
+		accel->x = getAxis(0, calibrated);
+		accel->y = getAxis(1, calibrated);
+		accel->z = getAxis(2, calibrated);
+		return 0;
+	}
+}
+
+// Given the returned record, extracts the value of the given axis. If
+// calibrated, then zero G is 0.0, and one G is 1.0.
+float getAxis(int which, int calibrated) {
+	// Get various values (to make code cleaner)
+	int indx = sensors[sensorNum].axes[which].index;
+	int size = sensors[sensorNum].axes[which].size;
+	float zerog = zeros[which];
+	float oneg = onegs[which];
+	// Storage for value to be returned
+	int value = 0;
+	
+	// Although the values in the returned record should have the proper
+	// endianness, we still have to get it into the proper end of value.
+#if (BYTE_ORDER == BIG_ENDIAN)
+	// On PowerPC processors
+	memcpy(((char *)&value) + (sizeof(int) - size), &oRecord[indx], size);
+#endif
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+	// On Intel processors
+	memcpy(&value, &oRecord[indx], size);
+#endif
+	
+	value = signExtend(value, size);
+	
+	if (calibrated) {
+		// Scale and shift for zero.
+		return ((float)(value - zerog)) / oneg;
+	} else {
+		return value;
+	}
+}
+
+// Extends the sign, given the length of the value.
+int signExtend(int value, int size) {
+	// Extend sign
+	switch (size) {
+		case 1:
+			if (value & 0x00000080)
+				value |= 0xffffff00;
+			break;
+		case 2:
+			if (value & 0x00008000)
+				value |= 0xffff0000;
+			break;
+		case 3:
+			if (value & 0x00800000)
+				value |= 0xff000000;
+			break;
+	}
+	return value;
+}
+
+// Returns the model name of the computer (e.g. "MacBookPro1,1")
+NSString *getModelName(void) {
+	char model[32];
+	size_t len = sizeof(model);
+	int name[2] = {CTL_HW, HW_MODEL};
+	NSString *result;
+	
+	if (sysctl(name, 2, &model, &len, NULL, 0) == 0) {
+		result = [NSString stringWithFormat:@"%s", model];
+	} else {
+		result = @"";
+	}
+	
+	return result;
+}
+
+// Returns the current OS X version and build (e.g. "10.4.7 (build 8J2135a)")
+NSString *getOSVersion(void) {
+	NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:
+		@"/System/Library/CoreServices/SystemVersion.plist"];
+	NSString *versionString = [dict objectForKey:@"ProductVersion"];
+	NSString *buildString = [dict objectForKey:@"ProductBuildVersion"];
+	NSString *wholeString = [NSString stringWithFormat:@"%@ (build %@)", 
+		versionString, buildString];
+	return wholeString;
+}
+
+// Returns time within the current second in microseconds.
+// long getMicroseconds() {
+//	struct timeval t;
+//	gettimeofday(&t, 0);
+//	return t.tv_usec;
+//}
+
+// Returns fake data given the time. Range is +/-1.
+float fakeData(NSTimeInterval time) {
+	long secs = lround(floor(time));
+	int secsMod3 = secs % 3;
+	double angle = time * 10 * M_PI * 2;
+	double mag = exp(-(time - (secs - secsMod3)) * 2);
+	return sin(angle) * mag;
+}
+	
--- a/dom/system/nsDeviceMotion.cpp
+++ b/dom/system/nsDeviceMotion.cpp
@@ -39,21 +39,24 @@
 #include "nsAutoPtr.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIServiceManager.h"
 #include "nsIPrivateDOMEvent.h"
-#include "nsIDOMDeviceOrientationEvent.h"
-#include "nsIDOMDeviceMotionEvent.h"
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
-#include "nsDOMDeviceMotionEvent.h"
+
+using mozilla::TimeStamp;
+using mozilla::TimeDuration;
+
+// also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java
+#define DEFAULT_SENSOR_POLL 100
 
 static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
     nsTArray<nsIDOMWindow*>::NoIndex;
 
 class nsDeviceMotionData : public nsIDeviceMotionData
 {
 public:
   NS_DECL_ISUPPORTS
@@ -112,31 +115,26 @@ NS_IMETHODIMP nsDeviceMotionData::GetZ(d
   *aZ = mZ;
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate)
 
 nsDeviceMotion::nsDeviceMotion()
 : mStarted(false),
-  mUpdateInterval(50), /* default to 50 ms */
   mEnabled(true)
 {
   nsCOMPtr<nsIPrefBranch> prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefSrv) {
-    PRInt32 value;
-    nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value);
-    if (NS_SUCCEEDED(rv))
-      mUpdateInterval = value;
-
     bool bvalue;
-    rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
+    nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
     if (NS_SUCCEEDED(rv) && bvalue == false)
       mEnabled = false;
   }
+  mLastDOMMotionEventTime = TimeStamp::Now();
 }
 
 nsDeviceMotion::~nsDeviceMotion()
 {
   if (mTimeoutTimer)
     mTimeoutTimer->Cancel();
 }
 
@@ -250,25 +248,85 @@ nsDeviceMotion::DeviceMotionChanged(PRUi
         pwindow->GetOuterWindow()->IsBackground())
       continue;
 
     nsCOMPtr<nsIDOMDocument> domdoc;
     windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
 
     if (domdoc) {
       nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
-      if (type == nsIDeviceMotionData::TYPE_ACCELERATION)
-        FireDOMMotionEvent(domdoc, target, x, y, z);
+      if (type == nsIDeviceMotionData::TYPE_ACCELERATION || 
+        type == nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION || 
+        type == nsIDeviceMotionData::TYPE_GYROSCOPE )
+        FireDOMMotionEvent(domdoc, target, type, x, y, z);
       else if (type == nsIDeviceMotionData::TYPE_ORIENTATION)
         FireDOMOrientationEvent(domdoc, target, x, y, z);
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDeviceMotion::NeedsCalibration()
+{
+  if (!mEnabled)
+    return NS_ERROR_NOT_INITIALIZED;
+
+  nsCOMArray<nsIDeviceMotionListener> listeners = mListeners;
+  for (PRUint32 i = listeners.Count(); i > 0 ; ) {
+    --i;
+    listeners[i]->NeedsCalibration();
+  }
+
+  nsCOMArray<nsIDOMWindow> windowListeners;
+  for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
+    windowListeners.AppendObject(mWindowListeners[i]);
+  }
+
+  for (PRUint32 i = windowListeners.Count(); i > 0 ; ) {
+    --i;
+
+    // check to see if this window is in the background.  if
+    // it is, don't send any device motion to it.
+    nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(windowListeners[i]);
+    if (!pwindow ||
+        !pwindow->GetOuterWindow() ||
+        pwindow->GetOuterWindow()->IsBackground())
+      continue;
+
+    nsCOMPtr<nsIDOMDocument> domdoc;
+    windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
+
+    if (domdoc) {
+	nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
+        FireNeedsCalibration(domdoc, target);
+    }
+  }
+
+  return NS_OK;
+}
+
+void
+nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc,
+				    nsIDOMEventTarget *target)
+{
+  nsCOMPtr<nsIDOMEvent> event;
+  domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
+  if (!event)
+    return;
+
+  event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false);
+  nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
+  if (privateEvent)
+    privateEvent->SetTrusted(true);
+  
+  bool defaultActionEnabled = true;
+  target->DispatchEvent(event, &defaultActionEnabled);
+}
+
 void
 nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc,
                                         nsIDOMEventTarget *target,
                                         double alpha,
                                         double beta,
                                         double gamma)
 {
   nsCOMPtr<nsIDOMEvent> event;
@@ -295,39 +353,62 @@ nsDeviceMotion::FireDOMOrientationEvent(
   
   target->DispatchEvent(event, &defaultActionEnabled);
 }
 
 
 void
 nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc,
                                    nsIDOMEventTarget *target,
+                                   PRUint32 type,
                                    double x,
                                    double y,
                                    double z) {
+  // Attempt to coalesce events
+  bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL);
+
+  switch (type) {
+  case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION:
+      mLastAcceleration = new nsDOMDeviceAcceleration(x, y, z);
+      break;
+  case nsIDeviceMotionData::TYPE_ACCELERATION:
+      mLastAccelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z);
+      break;
+  case nsIDeviceMotionData::TYPE_GYROSCOPE:
+      mLastRotationRate = new nsDOMDeviceRotationRate(x, y, z);
+      break;
+  }
+
+  if (!fireEvent && (!mLastAcceleration || !mLastAccelerationIncluduingGravity || !mLastRotationRate)) {
+      return;
+  }
+
   nsCOMPtr<nsIDOMEvent> event;
-  bool defaultActionEnabled = true;
   domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event));
 
   nsCOMPtr<nsIDOMDeviceMotionEvent> me = do_QueryInterface(event);
 
   if (!me) {
     return;
-}
-
-  // Currently acceleration as determined includes gravity.
-  nsRefPtr<nsDOMDeviceAcceleration> acceleration = new nsDOMDeviceAcceleration(x, y, z);
+  }
 
   me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"),
                             true,
                             false,
-                            nsnull,
-                            acceleration,
-                            nsnull,
-                            0);
+                            mLastAcceleration,
+                            mLastAccelerationIncluduingGravity,
+                            mLastRotationRate,
+                            DEFAULT_SENSOR_POLL);
 
   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
   if (privateEvent)
     privateEvent->SetTrusted(true);
   
+  bool defaultActionEnabled = true;
   target->DispatchEvent(event, &defaultActionEnabled);
+
+  mLastRotationRate = nsnull;
+  mLastAccelerationIncluduingGravity = nsnull;
+  mLastAcceleration = nsnull;
+  mLastDOMMotionEventTime = TimeStamp::Now();
+
 }
 
--- a/dom/system/nsDeviceMotion.h
+++ b/dom/system/nsDeviceMotion.h
@@ -38,16 +38,20 @@
 #define nsDeviceMotion_h
 
 #include "nsIDeviceMotion.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsCOMPtr.h"
 #include "nsITimer.h"
+#include "nsIDOMDeviceOrientationEvent.h"
+#include "nsIDOMDeviceMotionEvent.h"
+#include "nsDOMDeviceMotionEvent.h"
+#include "mozilla/TimeStamp.h"
 
 #define NS_DEVICE_MOTION_CID \
 { 0xecba5203, 0x77da, 0x465a, \
 { 0x86, 0x5e, 0x78, 0xb7, 0xaf, 0x10, 0xd8, 0xf7 } }
 
 #define NS_DEVICE_MOTION_CONTRACTID "@mozilla.org/devicemotion;1"
 
 class nsIDOMWindow;
@@ -71,28 +75,36 @@ private:
 
   bool mStarted;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   static void TimeoutHandler(nsITimer *aTimer, void *aClosure);
 
  protected:
 
+  void FireNeedsCalibration(nsIDOMDocument *domdoc,
+			    nsIDOMEventTarget *target);
+
   void FireDOMOrientationEvent(class nsIDOMDocument *domDoc, 
                                class nsIDOMEventTarget *target,
                                double alpha,
                                double beta,
                                double gamma);
 
   void FireDOMMotionEvent(class nsIDOMDocument *domDoc, 
                           class nsIDOMEventTarget *target,
+                          PRUint32 type,
                           double x,
                           double y,
                           double z);
 
-  PRUint32 mUpdateInterval;
-  bool     mEnabled;
-
   virtual void Startup()  = 0;
   virtual void Shutdown() = 0;
+
+  bool mEnabled;
+  mozilla::TimeStamp mLastDOMMotionEventTime;
+  nsRefPtr<nsDOMDeviceAcceleration> mLastAcceleration;
+  nsRefPtr<nsDOMDeviceAcceleration> mLastAccelerationIncluduingGravity;
+  nsRefPtr<nsDOMDeviceRotationRate> mLastRotationRate;
+
 };
 
 #endif
--- a/dom/system/unix/Makefile.in
+++ b/dom/system/unix/Makefile.in
@@ -77,9 +77,12 @@ CPPSRCS         += $(MOCSRCS) \
                    nsQTMDeviceMotionSystem.cpp \
                    $(NULL)
 LOCAL_INCLUDES  += $(MOZ_QT_CFLAGS) \
                    -I$(topsrcdir)/dom/src/geolocation \
                    $(NULL)
 endif
 endif
 
+# We fire the nsDOMDeviceAcceleration
+LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
+
 include $(topsrcdir)/config/rules.mk
--- a/dom/system/unix/nsDeviceMotionSystem.cpp
+++ b/dom/system/unix/nsDeviceMotionSystem.cpp
@@ -37,16 +37,18 @@
 
 #include <unistd.h>
 
 #include "mozilla/Util.h"
 
 #include "nsDeviceMotionSystem.h"
 #include "nsIServiceManager.h"
 
+#define DEFAULT_SENSOR_POLL 100
+
 using namespace mozilla;
 
 typedef struct {
   const char* mPosition;
   const char* mCalibrate;
   nsAccelerometerSystemDriver mToken;
 } AccelerometerData;
 
@@ -218,17 +220,17 @@ void nsDeviceMotionSystem::Startup()
 
   if (mType == eNoSensor)
     return;
 
   mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1");
   if (mUpdateTimer)
     mUpdateTimer->InitWithFuncCallback(UpdateHandler,
                                        this,
-                                       mUpdateInterval,
+                                       DEFAULT_SENSOR_POLL,
                                        nsITimer::TYPE_REPEATING_SLACK);
 }
 
 void nsDeviceMotionSystem::Shutdown()
 {
   if (mPositionFile) {
     fclose(mPositionFile);
     mPositionFile = nsnull;
--- a/dom/system/windows/Makefile.in
+++ b/dom/system/windows/Makefile.in
@@ -44,16 +44,19 @@ include $(DEPTH)/config/autoconf.mk
 MODULE      = dom
 LIBRARY_NAME    = domsystemwindows_s
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
+# We fire the nsDOMDeviceAcceleration
+LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
+
 include $(topsrcdir)/config/config.mk
 
 CPPSRCS     = \
         nsDeviceMotionSystem.cpp \
         nsHapticFeedback.cpp \
         $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/system/windows/nsDeviceMotionSystem.cpp
+++ b/dom/system/windows/nsDeviceMotionSystem.cpp
@@ -34,16 +34,18 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDeviceMotionSystem.h"
 #include "nsIServiceManager.h"
 #include "windows.h"
 
+#define DEFAULT_SENSOR_POLL 100
+
 ////////////////////////////
 // ThinkPad
 ////////////////////////////
 
 typedef struct {
   int status; // Current internal state
   unsigned short x; // raw value
   unsigned short y; // raw value
@@ -151,17 +153,17 @@ void nsDeviceMotionSystem::Startup()
     mSensor = nsnull;
     return;
   }
 
   mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1");
   if (mUpdateTimer)
     mUpdateTimer->InitWithFuncCallback(UpdateHandler,
                                        this,
-                                       mUpdateInterval,
+                                       DEFAULT_SENSOR_POLL,
                                        nsITimer::TYPE_REPEATING_SLACK);
 }
 
 void nsDeviceMotionSystem::Shutdown()
 {
   if (mUpdateTimer) {
     mUpdateTimer->Cancel();
     mUpdateTimer = nsnull;
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -159,18 +159,18 @@ Telephony::Create(nsPIDOMWindow* aOwner,
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
   NS_ENSURE_TRUE(sgo, nsnull);
 
   nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
   NS_ENSURE_TRUE(scriptContext, nsnull);
 
   nsRefPtr<Telephony> telephony = new Telephony();
 
-  telephony->mOwner = aOwner;
-  telephony->mScriptContext.swap(scriptContext);
+  telephony->BindToOwner(aOwner);
+
   telephony->mRIL = aRIL;
   telephony->mRILTelephonyCallback = new RILTelephonyCallback(telephony);
 
   nsresult rv = aRIL->EnumerateCalls(telephony->mRILTelephonyCallback);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
   rv = aRIL->RegisterCallback(telephony->mRILTelephonyCallback);
   NS_ENSURE_SUCCESS(rv, nsnull);
@@ -323,41 +323,52 @@ Telephony::SetSpeakerEnabled(bool aSpeak
 NS_IMETHODIMP
 Telephony::GetActive(jsval* aActive)
 {
   if (!mActiveCall) {
     aActive->setNull();
     return NS_OK;
   }
 
-  nsresult rv =
-    nsContentUtils::WrapNative(mScriptContext->GetNativeContext(),
-                               mScriptContext->GetNativeGlobal(),
-                               mActiveCall->ToISupports(), aActive);
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
-
+  if (sc) {
+    rv =
+      nsContentUtils::WrapNative(sc->GetNativeContext(),
+                                 sc->GetNativeGlobal(),
+                                 mActiveCall->ToISupports(), aActive);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::GetCalls(jsval* aCalls)
 {
   JSObject* calls = mCallsArray;
   if (!calls) {
-    nsresult rv =
-      nsTArrayToJSArray(mScriptContext->GetNativeContext(),
-                        mScriptContext->GetNativeGlobal(), mCalls, &calls);
+    nsresult rv;
+    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS(rv, rv);
+    if (sc) {
+      rv =
+        nsTArrayToJSArray(sc->GetNativeContext(),
+                          sc->GetNativeGlobal(), mCalls, &calls);
+      NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!mRooted) {
-      NS_HOLD_JS_OBJECTS(this, Telephony);
-      mRooted = true;
+      if (!mRooted) {
+        NS_HOLD_JS_OBJECTS(this, Telephony);
+        mRooted = true;
+      }
+
+      mCallsArray = calls;
+    } else {
+      NS_ENSURE_SUCCESS(rv, rv);
     }
-
-    mCallsArray = calls;
   }
 
   aCalls->setObject(*calls);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::StartTone(const nsAString& aDTMFChar)
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -113,28 +113,16 @@ public:
   }
 
   nsIRadioInterfaceLayer*
   RIL() const
   {
     return mRIL;
   }
 
-  nsPIDOMWindow*
-  Owner() const
-  {
-    return mOwner;
-  }
-
-  nsIScriptContext*
-  ScriptContext() const
-  {
-    return mScriptContext;
-  }
-
 private:
   Telephony();
   ~Telephony();
 
   already_AddRefed<TelephonyCall>
   CreateNewDialingCall(const nsAString& aNumber);
 
   void
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -52,18 +52,18 @@ TelephonyCall::Create(Telephony* aTeleph
                       PRUint16 aCallState, PRUint32 aCallIndex)
 {
   NS_ASSERTION(aTelephony, "Null pointer!");
   NS_ASSERTION(!aNumber.IsEmpty(), "Empty number!");
   NS_ASSERTION(aCallIndex >= 1, "Invalid call index!");
 
   nsRefPtr<TelephonyCall> call = new TelephonyCall();
 
-  call->mOwner = aTelephony->Owner();
-  call->mScriptContext = aTelephony->ScriptContext();
+  call->BindToOwner(aTelephony->GetOwner());
+
   call->mTelephony = aTelephony;
   call->mNumber = aNumber;
   call->mCallIndex = aCallIndex;
 
   call->ChangeStateInternal(aCallState, false);
 
   return call.forget();
 }
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -247,20 +247,19 @@ public class GeckoEvent {
             mType = PROXIMITY_EVENT;
             mDistance = s.values[0];
             Log.i("GeckoEvent", "SensorEvent type = " + s.sensor.getType() + 
                   " " + s.sensor.getName() + " " + mDistance);
             break;
         }
     }
 
-    public GeckoEvent(Location l, Address a) {
+    public GeckoEvent(Location l) {
         mType = LOCATION_EVENT;
         mLocation = l;
-        mAddress  = a;
     }
 
     public GeckoEvent(int imeAction, int offset, int count) {
         mType = IME_EVENT;
         mAction = imeAction;
         mOffset = offset;
         mCount = count;
     }
--- a/embedding/android/GeckoSurfaceView.java
+++ b/embedding/android/GeckoSurfaceView.java
@@ -575,57 +575,20 @@ class GeckoSurfaceView
     {
     }
 
     public void onSensorChanged(SensorEvent event)
     {
         GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
     }
 
-    private class GeocoderTask extends AsyncTask<Location, Void, Void> {
-        protected Void doInBackground(Location... location) {
-            try {
-                List<Address> addresses = mGeocoder.getFromLocation(location[0].getLatitude(),
-                                                                    location[0].getLongitude(), 1);
-                // grab the first address.  in the future,
-                // may want to expose multiple, or filter
-                // for best.
-                mLastGeoAddress = addresses.get(0);
-                GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress));
-            } catch (Exception e) {
-                Log.w(LOG_FILE_NAME, "GeocoderTask "+e);
-            }
-            return null;
-        }
-    }
-
     // geolocation
     public void onLocationChanged(Location location)
     {
-        if (mGeocoder == null)
-            mGeocoder = new Geocoder(getContext(), Locale.getDefault());
-
-        if (mLastGeoAddress == null) {
-            new GeocoderTask().execute(location);
-        }
-        else {
-            float[] results = new float[1];
-            Location.distanceBetween(location.getLatitude(),
-                                     location.getLongitude(),
-                                     mLastGeoAddress.getLatitude(),
-                                     mLastGeoAddress.getLongitude(),
-                                     results);
-            // pfm value.  don't want to slam the
-            // geocoder with very similar values, so
-            // only call after about 100m
-            if (results[0] > 100)
-                new GeocoderTask().execute(location);
-        }
-
-        GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress));
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(location));
     }
 
     public void onProviderDisabled(String provider)
     {
     }
 
     public void onProviderEnabled(String provider)
     {
@@ -820,14 +783,11 @@ class GeckoSurfaceView
     String mIMEActionHint;
     boolean mIMELandscapeFS;
 
     // Software rendering
     Bitmap mSoftwareBitmap;
     ByteBuffer mSoftwareBuffer;
     Bitmap mSoftwareBufferCopy;
 
-    Geocoder mGeocoder;
-    Address  mLastGeoAddress;
-
     final SynchronousQueue<Object> mSyncDraws = new SynchronousQueue<Object>();
 }
 
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -37,31 +37,42 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "gfxAndroidPlatform.h"
 #include "mozilla/gfx/2D.h"
 
 #include "gfxFT2FontList.h"
 #include "gfxImageSurface.h"
 #include "nsXULAppAPI.h"
+#include "nsIScreen.h"
+#include "nsIScreenManager.h"
 
 #include "cairo.h"
 
 #include "ft2build.h"
 #include FT_FREETYPE_H
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 static FT_Library gPlatformFTLibrary = NULL;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoFonts" , ## args)
 
 gfxAndroidPlatform::gfxAndroidPlatform()
 {
     FT_Init_FreeType(&gPlatformFTLibrary);
+
+    nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
+    nsCOMPtr<nsIScreen> screen;
+    screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
+    PRInt32 depth = 24;
+    screen->GetColorDepth(&depth);
+
+    mOffscreenFormat = depth == 16 ? gfxASurface::ImageFormatRGB16_565 :
+                                     gfxASurface::ImageFormatARGB32;
 }
 
 gfxAndroidPlatform::~gfxAndroidPlatform()
 {
     cairo_debug_reset_static_data();
 
     FT_Done_FreeType(gPlatformFTLibrary);
     gPlatformFTLibrary = NULL;
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -63,17 +63,17 @@ public:
     }
 
     virtual already_AddRefed<gfxASurface>
     CreateOffscreenSurface(const gfxIntSize& size,
                            gfxASurface::gfxContentType contentType);
     
     virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
 
-    virtual gfxImageFormat GetOffscreenFormat() { return gfxASurface::ImageFormatRGB16_565; }
+    virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
     
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
       GetScaledFontForFont(gfxFont *aFont);
 
     // to support IPC font list (sharing between chrome and content)
     void GetFontList(InfallibleTArray<FontListEntry>* retValue);
 
     // platform implementations of font functions
@@ -97,12 +97,15 @@ public:
 
     virtual gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
                                           const gfxFontStyle *aStyle,
                                           gfxUserFontSet* aUserFontSet);
 
     virtual bool FontHintingEnabled() MOZ_OVERRIDE;
 
     FT_Library GetFTLibrary();
+
+private:
+    gfxImageFormat mOffscreenFormat;
 };
 
 #endif /* GFX_PLATFORM_ANDROID_H */
 
--- a/hal/HalSensor.h
+++ b/hal/HalSensor.h
@@ -49,16 +49,18 @@ namespace hal {
  * Enumeration of sensor types.  They are used to specify type while
  * register or unregister an observer for a sensor of given type.
  */
 enum SensorType {
   SENSOR_UNKNOWN = -1,
   SENSOR_ORIENTATION,
   SENSOR_ACCELERATION,
   SENSOR_PROXIMITY,
+  SENSOR_LINEAR_ACCELERATION,
+  SENSOR_GYROSCOPE,
   NUM_SENSOR_TYPE
 };
 
 class SensorData;
 
 typedef Observer<SensorData> ISensorObserver;
 
 }
--- a/ipc/chromium/src/base/platform_thread_mac.mm
+++ b/ipc/chromium/src/base/platform_thread_mac.mm
@@ -1,15 +1,16 @@
 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/platform_thread.h"
 
 #import <Foundation/Foundation.h>
+#include <dlfcn.h>
 
 #include "base/logging.h"
 #include "base/scoped_nsautorelease_pool.h"
 
 // A simple class that demonstrates our impressive ability to do nothing.
 @interface NoOp : NSObject
 
 // Does the deed.  Or does it?
@@ -46,8 +47,31 @@ void InitThreading() {
                            withObject:nil];
     multithreaded = YES;
 
     DCHECK([NSThread isMultiThreaded]);
   }
 }
 
 }  // namespace base
+
+// static
+void PlatformThread::SetName(const char* name) {
+  // pthread_setname_np is only available in 10.6 or later, so test
+  // for it at runtime.
+  int (*dynamic_pthread_setname_np)(const char*);
+  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
+      dlsym(RTLD_DEFAULT, "pthread_setname_np");
+  if (!dynamic_pthread_setname_np)
+    return;
+
+  // Mac OS X does not expose the length limit of the name, so
+  // hardcode it.
+  const int kMaxNameLength = 63;
+  std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
+  // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
+  // See http://crbug.com/47058
+
+  // The name parameter is copied thus it's safe to release it after calling.
+  // Checked against the bionic implementation in bionic/libc/bionic/pthread.c
+  dynamic_pthread_setname_np(shortened_name.c_str());
+}
+
--- a/ipc/chromium/src/base/platform_thread_posix.cc
+++ b/ipc/chromium/src/base/platform_thread_posix.cc
@@ -56,25 +56,29 @@ void PlatformThread::Sleep(int duration_
 
   // Contains the portion of duration_ms < 1 sec.
   sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.
 
   while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
     sleep_time = remaining;
 }
 
+#ifndef OS_MACOSX
+// Mac is implemented in platform_thread_mac.mm.
+
 // static
 void PlatformThread::SetName(const char* name) {
   // The POSIX standard does not provide for naming threads, and neither Linux
   // nor Mac OS X (our two POSIX targets) provide any non-portable way of doing
   // it either. (Some BSDs provide pthread_set_name_np but that isn't much of a
   // consolation prize.)
   // TODO(darin): decide whether stuffing the name in TLS or other in-memory
   // structure would be useful for debugging or not.
 }
+#endif // !OS_MACOSX
 
 namespace {
 
 bool CreateThread(size_t stack_size, bool joinable,
                   PlatformThread::Delegate* delegate,
                   PlatformThreadHandle* thread_handle) {
 #if defined(OS_MACOSX)
   base::InitThreading();
--- a/js/src/config/milestone.txt
+++ b/js/src/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by milestone.pl.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-13.0a1
+14.0a1
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -49,143 +49,348 @@
 #include "jsutil.h"
 #include "prmjtime.h"
 
 #include "gc/Statistics.h"
 
 namespace js {
 namespace gcstats {
 
+/* Except for the first and last, slices of less than 12ms are not reported. */
+static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC;
+
+class StatisticsSerializer
+{
+    typedef Vector<char, 128, SystemAllocPolicy> CharBuffer;
+    CharBuffer buf_;
+    bool asJSON_;
+    bool needComma_;
+    bool oom_;
+
+    const static int MaxFieldValueLength = 128;
+
+  public:
+    enum Mode {
+        AsJSON = true,
+        AsText = false
+    };
+
+    StatisticsSerializer(Mode asJSON)
+      : buf_(), asJSON_(asJSON), needComma_(false), oom_(false)
+    {}
+
+    bool isJSON() { return asJSON_; }
+
+    bool isOOM() { return oom_; }
+
+    void endLine() {
+        if (!asJSON_) {
+            p("\n");
+            needComma_ = false;
+        }
+    }
+
+    void extra(const char *str) {
+        if (!asJSON_) {
+            needComma_ = false;
+            p(str);
+        }
+    }
+
+    void appendString(const char *name, const char *value) {
+        put(name, value, "", true);
+    }
+
+    void appendNumber(const char *name, const char *vfmt, const char *units, ...) {
+        va_list va;
+        va_start(va, units);
+        append(name, vfmt, va, units);
+        va_end(va);
+    }
+
+    void appendIfNonzeroMS(const char *name, double v) {
+        if (asJSON_ || v)
+            appendNumber(name, "%.1f", "ms", v);
+    }
+
+    void beginObject(const char *name) {
+        if (needComma_)
+            pJSON(", ");
+        if (asJSON_ && name) {
+            putQuoted(name);
+            pJSON(": ");
+        }
+        pJSON("{");
+        needComma_ = false;
+    }
+
+    void endObject() {
+        needComma_ = false;
+        pJSON("}");
+        needComma_ = true;
+    }
+
+    void beginArray(const char *name) {
+        if (needComma_)
+            pJSON(", ");
+        if (asJSON_)
+            putQuoted(name);
+        pJSON(": [");
+        needComma_ = false;
+    }
+
+    void endArray() {
+        needComma_ = false;
+        pJSON("]");
+        needComma_ = true;
+    }
+
+    jschar *finishJSString() {
+        char *buf = finishCString();
+        if (!buf)
+            return NULL;
+
+        size_t nchars = strlen(buf);
+        jschar *out = (jschar *)js_malloc(sizeof(jschar) * (nchars + 1));
+        if (!out) {
+            oom_ = true;
+            js_free(buf);
+            return NULL;
+        }
+
+        size_t outlen = nchars;
+        bool ok = InflateStringToBuffer(NULL, buf, nchars, out, &outlen);
+        js_free(buf);
+        if (!ok) {
+            oom_ = true;
+            js_free(out);
+            return NULL;
+        }
+        out[nchars] = 0;
+
+        return out;
+    }
+
+    char *finishCString() {
+        if (oom_)
+            return NULL;
+
+        buf_.append('\0');
+
+        char *buf = buf_.extractRawBuffer();
+        if (!buf)
+            oom_ = true;
+
+        return buf;
+    }
+
+  private:
+    void append(const char *name, const char *vfmt,
+                va_list va, const char *units)
+    {
+        char val[MaxFieldValueLength];
+        JS_vsnprintf(val, MaxFieldValueLength, vfmt, va);
+        put(name, val, units, false);
+    }
+
+    void p(const char *cstr) {
+        if (oom_)
+            return;
+
+        if (!buf_.append(cstr, strlen(cstr)))
+            oom_ = true;
+    }
+
+    void p(const char c) {
+        if (oom_)
+            return;
+
+        if (!buf_.append(c))
+            oom_ = true;
+    }
+
+    void pJSON(const char *str) {
+        if (asJSON_)
+            p(str);
+    }
+
+    void put(const char *name, const char *val, const char *units, bool valueIsQuoted) {
+        if (needComma_)
+            p(", ");
+        needComma_ = true;
+
+        putKey(name);
+        p(": ");
+        if (valueIsQuoted)
+            putQuoted(val);
+        else
+            p(val);
+        if (!asJSON_)
+            p(units);
+    }
+
+    void putQuoted(const char *str) {
+        pJSON("\"");
+        p(str);
+        pJSON("\"");
+    }
+
+    void putKey(const char *str) {
+        if (!asJSON_) {
+            p(str);
+            return;
+        }
+
+        p("\"");
+        const char *c = str;
+        while (*c) {
+            if (*c == ' ' || *c == '\t')
+                p('_');
+            else if (isupper(*c))
+                p(tolower(*c));
+            else if (*c == '+')
+                p("added_");
+            else if (*c == '-')
+                p("removed_");
+            else if (*c != '(' && *c != ')')
+                p(*c);
+            c++;
+        }
+        p("\"");
+    }
+};
+
 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
     }
 }
 
-void
-Statistics::fmt(const char *f, ...)
+static double
+t(int64_t t)
 {
-    va_list va;
-    size_t off = strlen(buffer);
-
-    va_start(va, f);
-    JS_vsnprintf(buffer + off, BUFFER_SIZE - off, f, va);
-    va_end(va);
-}
-
-void
-Statistics::fmtIfNonzero(const char *name, double t)
-{
-    if (t) {
-        if (needComma)
-            fmt(", ");
-        fmt("%s: %.1f", name, t);
-        needComma = true;
-    }
+    return double(t) / PRMJ_USEC_PER_MSEC;
 }
 
-void
-Statistics::formatPhases(int64_t *times)
+static void
+formatPhases(StatisticsSerializer &ss, const char *name, int64_t *times)
 {
-    needComma = false;
-    fmtIfNonzero("mark", t(times[PHASE_MARK]));
-    fmtIfNonzero("mark-roots", t(times[PHASE_MARK_ROOTS]));
-    fmtIfNonzero("mark-delayed", t(times[PHASE_MARK_DELAYED]));
-    fmtIfNonzero("mark-other", t(times[PHASE_MARK_OTHER]));
-    fmtIfNonzero("sweep", t(times[PHASE_SWEEP]));
-    fmtIfNonzero("sweep-obj", t(times[PHASE_SWEEP_OBJECT]));
-    fmtIfNonzero("sweep-string", t(times[PHASE_SWEEP_STRING]));
-    fmtIfNonzero("sweep-script", t(times[PHASE_SWEEP_SCRIPT]));
-    fmtIfNonzero("sweep-shape", t(times[PHASE_SWEEP_SHAPE]));
-    fmtIfNonzero("discard-code", t(times[PHASE_DISCARD_CODE]));
-    fmtIfNonzero("discard-analysis", t(times[PHASE_DISCARD_ANALYSIS]));
-    fmtIfNonzero("xpconnect", t(times[PHASE_XPCONNECT]));
-    fmtIfNonzero("deallocate", t(times[PHASE_DESTROY]));
+    ss.beginObject(name);
+    ss.appendIfNonzeroMS("Mark", t(times[PHASE_MARK]));
+    ss.appendIfNonzeroMS("Mark Roots", t(times[PHASE_MARK_ROOTS]));
+    ss.appendIfNonzeroMS("Mark Delayed", t(times[PHASE_MARK_DELAYED]));
+    ss.appendIfNonzeroMS("Mark Other", t(times[PHASE_MARK_OTHER]));
+    ss.appendIfNonzeroMS("Sweep", t(times[PHASE_SWEEP]));
+    ss.appendIfNonzeroMS("Sweep Object", t(times[PHASE_SWEEP_OBJECT]));
+    ss.appendIfNonzeroMS("Sweep String", t(times[PHASE_SWEEP_STRING]));
+    ss.appendIfNonzeroMS("Sweep Script", t(times[PHASE_SWEEP_SCRIPT]));
+    ss.appendIfNonzeroMS("Sweep Shape", t(times[PHASE_SWEEP_SHAPE]));
+    ss.appendIfNonzeroMS("Discard Code", t(times[PHASE_DISCARD_CODE]));
+    ss.appendIfNonzeroMS("Discard Analysis", t(times[PHASE_DISCARD_ANALYSIS]));
+    ss.appendIfNonzeroMS("XPConnect", t(times[PHASE_XPCONNECT]));
+    ss.appendIfNonzeroMS("Deallocate", t(times[PHASE_DESTROY]));
+    ss.endObject();
 }
 
-/* Except for the first and last, slices of less than 12ms are not reported. */
-static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC;
-
-const char *
-Statistics::formatData()
+bool
+Statistics::formatData(StatisticsSerializer &ss)
 {
-    buffer[0] = 0x00;
-
     int64_t total = 0, longest = 0;
-
     for (SliceData *slice = slices.begin(); slice != slices.end(); slice++) {
         total += slice->duration();
         if (slice->duration() > longest)
             longest = slice->duration();
     }
 
     double mmu20 = computeMMU(20 * PRMJ_USEC_PER_MSEC);
     double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC);
 
-    fmt("TotalTime: %.1fms, Type: %s", t(total), compartment ? "compartment" : "global");
-    fmt(", MMU(20ms): %d%%, MMU(50ms): %d%%", int(mmu20 * 100), int(mmu50 * 100));
-
-    if (slices.length() > 1)
-        fmt(", MaxPause: %.1f", t(longest));
+    ss.beginObject(NULL);
+    ss.appendNumber("Total Time", "%.1f", "ms", t(total));
+    ss.appendString("Type", compartment ? "compartment" : "global");
+    ss.appendNumber("MMU (20ms)", "%d", "%", int(mmu20 * 100));
+    ss.appendNumber("MMU (50ms)", "%d", "%", int(mmu50 * 100));
+    if (slices.length() > 1 || ss.isJSON())
+        ss.appendNumber("Max Pause", "%.1f", "ms", t(longest));
     else
-        fmt(", Reason: %s", ExplainReason(slices[0].reason));
+        ss.appendString("Reason", ExplainReason(slices[0].reason));
+    if (nonincrementalReason || ss.isJSON()) {
+        ss.appendString("Nonincremental Reason",
+                        nonincrementalReason ? nonincrementalReason : "none");
+    }
+    ss.appendNumber("+Chunks", "%d", "", counts[STAT_NEW_CHUNK]);
+    ss.appendNumber("-Chunks", "%d", "", counts[STAT_DESTROY_CHUNK]);
+    ss.endLine();
 
-    if (nonincrementalReason)
-        fmt(", NonIncrementalReason: %s", nonincrementalReason);
-
-    fmt(", +chunks: %d, -chunks: %d\n", counts[STAT_NEW_CHUNK], counts[STAT_DESTROY_CHUNK]);
-
-    if (slices.length() > 1) {
+    if (slices.length() > 1 || ss.isJSON()) {
+        ss.beginArray("Slices");
         for (size_t i = 0; i < slices.length(); i++) {
             int64_t width = slices[i].duration();
             if (i != 0 && i != slices.length() - 1 && width < SLICE_MIN_REPORT_TIME &&
-                !slices[i].resetReason)
+                !slices[i].resetReason && !ss.isJSON())
             {
                 continue;
             }
 
-            fmt("    Slice %d @ %.1fms (Pause: %.1f, Reason: %s",
-                i,
-                t(slices[i].end - slices[0].start),
-                t(width),
-                ExplainReason(slices[i].reason));
+            ss.beginObject(NULL);
+            ss.extra("    ");
+            ss.appendNumber("Slice", "%d", "", i);
+            ss.appendNumber("Time", "%.1f", "ms", t(slices[i].end - slices[0].start));
+            ss.extra(" (");
+            ss.appendNumber("Pause", "%.1f", "", t(width));
+            ss.appendString("Reason", ExplainReason(slices[i].reason));
             if (slices[i].resetReason)
-                fmt(", Reset: %s", slices[i].resetReason);
-            fmt("): ");
-            formatPhases(slices[i].phaseTimes);
-            fmt("\n");
+                ss.appendString("Reset", slices[i].resetReason);
+            ss.extra("): ");
+            formatPhases(ss, "times", slices[i].phaseTimes);
+            ss.endLine();
+            ss.endObject();
         }
+        ss.endArray();
+    }
+    ss.extra("    Totals: ");
+    formatPhases(ss, "totals", phaseTimes);
+    ss.endObject();
+
+    return !ss.isOOM();
+}
 
-        fmt("    Totals: ");
-    }
+jschar *
+Statistics::formatMessage()
+{
+    StatisticsSerializer ss(StatisticsSerializer::AsText);
+    formatData(ss);
+    return ss.finishJSString();
+}
 
-    formatPhases(phaseTimes);
-    fmt("\n");
-
-    return buffer;
+jschar *
+Statistics::formatJSON()
+{
+    StatisticsSerializer ss(StatisticsSerializer::AsJSON);
+    formatData(ss);
+    return ss.finishJSString();
 }
 
 Statistics::Statistics(JSRuntime *rt)
   : runtime(rt),
     startupTime(PRMJ_Now()),
     fp(NULL),
     fullFormat(false),
     compartment(NULL),
-    nonincrementalReason(NULL),
-    needComma(false)
+    nonincrementalReason(NULL)
 {
     PodArrayZero(phaseTotals);
     PodArrayZero(counts);
 
     char *env = getenv("MOZ_GCTIMER");
     if (!env || strcmp(env, "none") == 0) {
         fp = NULL;
         return;
@@ -204,45 +409,47 @@ Statistics::Statistics(JSRuntime *rt)
         JS_ASSERT(fp);
     }
 }
 
 Statistics::~Statistics()
 {
     if (fp) {
         if (fullFormat) {
-            buffer[0] = 0x00;
-            formatPhases(phaseTotals);
-            fprintf(fp, "TOTALS\n%s\n\n-------\n", buffer);
+            StatisticsSerializer ss(StatisticsSerializer::AsText);
+            formatPhases(ss, "", phaseTotals);
+            char *msg = ss.finishCString();
+            if (msg) {
+                fprintf(fp, "TOTALS\n%s\n\n-------\n", msg);
+                js_free(msg);
+            }
         }
 
         if (fp != stdout && fp != stderr)
             fclose(fp);
     }
 }
 
-double
-Statistics::t(int64_t t)
-{
-    return double(t) / PRMJ_USEC_PER_MSEC;
-}
-
 int64_t
 Statistics::gcDuration()
 {
     return slices.back().end - slices[0].start;
 }
 
 void
 Statistics::printStats()
 {
     if (fullFormat) {
-        fprintf(fp, "GC(T+%.3fs) %s\n",
-                t(slices[0].start - startupTime) / 1000.0,
-                formatData());
+        StatisticsSerializer ss(StatisticsSerializer::AsText);
+        formatData(ss);
+        char *msg = ss.finishCString();
+        if (msg) {
+            fprintf(fp, "GC(T+%.3fs) %s\n", t(slices[0].start - startupTime) / 1000.0, msg);
+            js_free(msg);
+        }
     } else {
         fprintf(fp, "%f %f %f\n",
                 t(gcDuration()),
                 t(phaseTimes[PHASE_MARK]),
                 t(phaseTimes[PHASE_SWEEP]));
     }
     fflush(fp);
 }
@@ -296,20 +503,18 @@ Statistics::beginSlice(JSCompartment *co
         beginGC();
 
     SliceData data(reason, PRMJ_Now());
     (void) slices.append(data); /* Ignore any OOMs here. */
 
     if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback)
         (*cb)(JS_TELEMETRY_GC_REASON, reason);
 
-    if (GCSliceCallback cb = runtime->gcSliceCallback) {
-        GCDescription desc(NULL, !!compartment);
-        (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, desc);
-    }
+    if (GCSliceCallback cb = runtime->gcSliceCallback)
+        (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, GCDescription(!!compartment));
 }
 
 void
 Statistics::endSlice()
 {
     slices.back().end = PRMJ_Now();
 
     if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
@@ -318,19 +523,19 @@ Statistics::endSlice()
     }
 
     bool last = runtime->gcIncrementalState == gc::NO_INCREMENTAL;
     if (last)
         endGC();
 
     if (GCSliceCallback cb = runtime->gcSliceCallback) {
         if (last)
-            (*cb)(runtime, GC_CYCLE_END, GCDescription(formatData(), !!compartment));
+            (*cb)(runtime, GC_CYCLE_END, GCDescription(!!compartment));
         else
-            (*cb)(runtime, GC_SLICE_END, GCDescription(NULL, !!compartment));
+            (*cb)(runtime, GC_SLICE_END, GCDescription(!!compartment));
     }
 }
 
 void
 Statistics::beginPhase(Phase phase)
 {
     phaseStarts[phase] = PRMJ_Now();
 
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -71,17 +71,17 @@ enum Phase {
 
 enum Stat {
     STAT_NEW_CHUNK,
     STAT_DESTROY_CHUNK,
 
     STAT_LIMIT
 };
 
-static const size_t BUFFER_SIZE = 8192;
+class StatisticsSerializer;
 
 struct Statistics {
     Statistics(JSRuntime *rt);
     ~Statistics();
 
     void beginPhase(Phase phase);
     void endPhase(Phase phase);
 
@@ -91,16 +91,19 @@ struct Statistics {
     void reset(const char *reason) { slices.back().resetReason = reason; }
     void nonincremental(const char *reason) { nonincrementalReason = reason; }
 
     void count(Stat s) {
         JS_ASSERT(s < STAT_LIMIT);
         counts[s]++;
     }
 
+    jschar *formatMessage();
+    jschar *formatJSON();
+
   private:
     JSRuntime *runtime;
 
     int64_t startupTime;
 
     FILE *fp;
     bool fullFormat;
 
@@ -131,29 +134,22 @@ struct Statistics {
     int64_t phaseTimes[PHASE_LIMIT];
 
     /* Total time in a given phase over all GCs. */
     int64_t phaseTotals[PHASE_LIMIT];
 
     /* Number of events of this type for this GC. */
     unsigned int counts[STAT_LIMIT];
 
-    char buffer[BUFFER_SIZE];
-    bool needComma;
-
     void beginGC();
     void endGC();
 
     int64_t gcDuration();
-    double t(int64_t t);
     void printStats();
-    void fmt(const char *f, ...);
-    void fmtIfNonzero(const char *name, double t);
-    void formatPhases(int64_t *times);
-    const char *formatData();
+    bool formatData(StatisticsSerializer &ss);
 
     double computeMMU(int64_t resolution);
 };
 
 struct AutoGCSlice {
     AutoGCSlice(Statistics &stats, JSCompartment *comp, gcreason::Reason reason
                 JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : stats(stats) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginSlice(comp, reason); }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4279,17 +4279,17 @@ prop_iter_trace(JSTracer *trc, JSObject 
         /* Non-native case: mark each id in the JSIdArray private. */
         JSIdArray *ida = (JSIdArray *) pdata;
         MarkIdRange(trc, ida->length, ida->vector, "prop iter");
     }
 }
 
 static Class prop_iter_class = {
     "PropertyIterator",
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
+    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     prop_iter_finalize,
@@ -6440,33 +6440,20 @@ JS_ClearPendingException(JSContext *cx)
 {
     AssertNoGC(cx);
     cx->clearPendingException();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ReportPendingException(JSContext *cx)
 {
-    JSBool ok;
-    bool save;
-
-    AssertNoGC(cx);
-    CHECK_REQUEST(cx);
-
-    /*
-     * Set cx->generatingError to suppress the standard error-to-exception
-     * conversion done by all {js,JS}_Report* functions except for OOM.  The
-     * cx->generatingError flag was added to suppress recursive divergence
-     * under js_ErrorToException, but it serves for our purposes here too.
-     */
-    save = cx->generatingError;
-    cx->generatingError = JS_TRUE;
-    ok = js_ReportUncaughtException(cx);
-    cx->generatingError = save;
-    return ok;
+    AssertNoGC(cx);
+    CHECK_REQUEST(cx);
+
+    return js_ReportUncaughtException(cx);
 }
 
 struct JSExceptionState {
     JSBool throwing;
     jsval  exception;
 };
 
 JS_PUBLIC_API(JSExceptionState *)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -115,17 +115,16 @@
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsscope.h"
-#include "jsstr.h"
 #include "jswrapper.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/StubCalls.h"
 #include "methodjit/StubCalls-inl.h"
 
 #include "vm/ArgumentsObject.h"
 #include "vm/MethodGuard.h"
 #include "vm/StringBuffer-inl.h"
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -822,35 +822,32 @@ struct JSContext : js::ContextFriendFiel
 
   private:
     /* See JSContext::findVersion. */
     JSVersion           defaultVersion;      /* script compilation version */
     JSVersion           versionOverride;     /* supercedes defaultVersion when valid */
     bool                hasVersionOverride;
 
     /* Exception state -- the exception member is a GC root by definition. */
-    JSBool              throwing;           /* is there a pending exception? */
-    js::Value           exception;          /* most-recently-thrown exception */
+    JSBool              throwing;            /* is there a pending exception? */
+    js::Value           exception;           /* most-recently-thrown exception */
 
     /* Per-context run options. */
-    unsigned               runOptions;            /* see jsapi.h for JSOPTION_* */
+    unsigned            runOptions;          /* see jsapi.h for JSOPTION_* */
 
   public:
     int32_t             reportGranularity;  /* see jsprobes.h */
 
     /* Locale specific callbacks for string conversion. */
     JSLocaleCallbacks   *localeCallbacks;
 
     js::AutoResolving   *resolvingList;
 
-    /*
-     * True if generating an error, to prevent runaway recursion.
-     * NB: generatingError packs with throwing below.
-     */
-    bool        generatingError;
+    /* True if generating an error, to prevent runaway recursion. */
+    bool                generatingError;
 
     /* GC heap compartment. */
     JSCompartment       *compartment;
 
     inline void setCompartment(JSCompartment *compartment);
 
     /* Current execution stack. */
     js::ContextStack    stack;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -1069,26 +1069,25 @@ static struct exnname { char *name; char
 JSBool
 js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
                     JSErrorCallback callback, void *userRef)
 {
     JSErrNum errorNumber;
     const JSErrorFormatString *errorString;
     JSExnType exn;
     jsval tv[4];
-    JSBool ok;
     JSObject *errProto, *errObject;
     JSString *messageStr, *filenameStr;
 
     /*
      * Tell our caller to report immediately if this report is just a warning.
      */
     JS_ASSERT(reportp);
     if (JSREPORT_IS_WARNING(reportp->flags))
-        return JS_FALSE;
+        return false;
 
     /* Find the exception index associated with this error. */
     errorNumber = (JSErrNum) reportp->errorNumber;
     if (!callback || callback == js_GetErrorMessage)
         errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
     else
         errorString = callback(userRef, NULL, errorNumber);
     exn = errorString ? (JSExnType) errorString->exnType : JSEXN_NONE;
@@ -1101,78 +1100,58 @@ js_ErrorToException(JSContext *cx, const
             errortoexnname[errorNumber].exception);
 #endif
 
     /*
      * Return false (no exception raised) if no exception is associated
      * with the given error number.
      */
     if (exn == JSEXN_NONE)
-        return JS_FALSE;
+        return false;
 
-    /*
-     * Prevent runaway recursion, via cx->generatingError.  If an out-of-memory
-     * error occurs, no exception object will be created, but we don't assume
-     * that OOM is the only kind of error that subroutines of this function
-     * called below might raise.
-     */
+    /* Prevent infinite recursion. */
     if (cx->generatingError)
-        return JS_FALSE;
-
-    MUST_FLOW_THROUGH("out");
-    cx->generatingError = JS_TRUE;
+        return false;
+    AutoScopedAssign<bool> asa(&cx->generatingError, true);
 
     /* Protect the newly-created strings below from nesting GCs. */
     PodArrayZero(tv);
     AutoArrayRooter tvr(cx, ArrayLength(tv), tv);
 
     /*
      * Try to get an appropriate prototype by looking up the corresponding
      * exception constructor name in the scope chain of the current context's
      * top stack frame, or in the global object if no frame is active.
      */
-    ok = js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto);
-    if (!ok)
-        goto out;
+    if (!js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto))
+        return false;
     tv[0] = OBJECT_TO_JSVAL(errProto);
 
-    errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
-    if (!errObject) {
-        ok = JS_FALSE;
-        goto out;
-    }
+    if (!(errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL)))
+        return false;
     tv[1] = OBJECT_TO_JSVAL(errObject);
 
-    messageStr = JS_NewStringCopyZ(cx, message);
-    if (!messageStr) {
-        ok = JS_FALSE;
-        goto out;
-    }
+    if (!(messageStr = JS_NewStringCopyZ(cx, message)))
+        return false;
     tv[2] = STRING_TO_JSVAL(messageStr);
 
-    filenameStr = JS_NewStringCopyZ(cx, reportp->filename);
-    if (!filenameStr) {
-        ok = JS_FALSE;
-        goto out;
-    }
+    if (!(filenameStr = JS_NewStringCopyZ(cx, reportp->filename)))
+        return false;
     tv[3] = STRING_TO_JSVAL(filenameStr);
 
-    ok = InitExnPrivate(cx, errObject, messageStr, filenameStr,
-                        reportp->lineno, reportp, exn);
-    if (!ok)
-        goto out;
+    if (!InitExnPrivate(cx, errObject, messageStr, filenameStr,
+                        reportp->lineno, reportp, exn)) {
+        return false;
+    }
 
     JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
 
     /* Flag the error report passed in to indicate an exception was raised. */
     reportp->flags |= JSREPORT_EXCEPTION;
-
-out:
-    cx->generatingError = JS_FALSE;
-    return ok;
+    return true;
 }
 
 JSBool
 js_ReportUncaughtException(JSContext *cx)
 {
     jsval exn;
     JSObject *exnObject;
     jsval roots[5];
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -712,16 +712,28 @@ SizeOfJSContext()
 JS_FRIEND_API(GCSliceCallback)
 SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
 {
     GCSliceCallback old = rt->gcSliceCallback;
     rt->gcSliceCallback = callback;
     return old;
 }
 
+jschar *
+GCDescription::formatMessage(JSRuntime *rt) const
+{
+    return rt->gcStats.formatMessage();
+}
+
+jschar *
+GCDescription::formatJSON(JSRuntime *rt) const
+{
+    return rt->gcStats.formatJSON();
+}
+
 JS_FRIEND_API(bool)
 WantGCSlice(JSRuntime *rt)
 {
     if (rt->gcZeal() == gc::ZealFrameVerifierValue || rt->gcZeal() == gc::ZealFrameGCValue)
         return true;
 
     if (rt->gcIncrementalState != gc::NO_INCREMENTAL)
         return true;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -694,22 +694,24 @@ enum GCProgress {
      */
 
     GC_CYCLE_BEGIN,
     GC_SLICE_BEGIN,
     GC_SLICE_END,
     GC_CYCLE_END
 };
 
-struct GCDescription {
-    const char *logMessage;
+struct JS_FRIEND_API(GCDescription) {
     bool isCompartment;
 
-    GCDescription(const char *msg, bool isCompartment)
-      : logMessage(msg), isCompartment(isCompartment) {}
+    GCDescription(bool isCompartment)
+      : isCompartment(isCompartment) {}
+
+    jschar *formatMessage(JSRuntime *rt) const;
+    jschar *formatJSON(JSRuntime *rt) const;
 };
 
 typedef void
 (* GCSliceCallback)(JSRuntime *rt, GCProgress progress, const GCDescription &desc);
 
 extern JS_FRIEND_API(GCSliceCallback)
 SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -6926,17 +6926,17 @@ mjit::Compiler::jsop_regexp()
      * script could actually observe the effect of such cloning, by getting
      * or setting properties on it. Particular RegExp and String natives take
      * regular expressions as 'this' or an argument, and do not let that
      * expression escape and be accessed by the script, so avoid cloning in
      * these cases.
      */
     analyze::SSAUseChain *uses =
         analysis->useChain(analyze::SSAValue::PushedValue(PC - script->code, 0));
-    if (uses && uses->popped && !uses->next) {
+    if (uses && uses->popped && !uses->next && !reobj->global() && !reobj->sticky()) {
         jsbytecode *use = script->code + uses->offset;
         uint32_t which = uses->u.which;
         if (JSOp(*use) == JSOP_CALLPROP) {
             JSObject *callee = analysis->pushedTypes(use, 0)->getSingleton(cx);
             if (callee && callee->isFunction()) {
                 Native native = callee->toFunction()->maybeNative();
                 if (native == js::regexp_exec || native == js::regexp_test) {
                     frame.push(ObjectValue(*obj));
--- a/js/src/tests/ecma_2/browser.js
+++ b/js/src/tests/ecma_2/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/ecma_3/Date/browser.js
+++ b/js/src/tests/ecma_3/Date/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/ecma_3/browser.js
+++ b/js/src/tests/ecma_3/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/ecma_3/shell.js
+++ b/js/src/tests/ecma_3/shell.js
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/ecma_3_1/browser.js
+++ b/js/src/tests/ecma_3_1/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/ecma_3_1/shell.js
+++ b/js/src/tests/ecma_3_1/shell.js
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/ecma_5/Array/browser.js
+++ b/js/src/tests/ecma_5/Array/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/Expressions/shell.js
+++ b/js/src/tests/ecma_5/Expressions/shell.js
@@ -1,7 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
--- a/js/src/tests/ecma_5/Function/browser.js
+++ b/js/src/tests/ecma_5/Function/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/Global/browser.js
+++ b/js/src/tests/ecma_5/Global/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/JSON/browser.js
+++ b/js/src/tests/ecma_5/JSON/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/Object/browser.js
+++ b/js/src/tests/ecma_5/Object/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/RegExp/browser.js
+++ b/js/src/tests/ecma_5/RegExp/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/String/browser.js
+++ b/js/src/tests/ecma_5/String/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/Types/browser.js
+++ b/js/src/tests/ecma_5/Types/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/browser.js
+++ b/js/src/tests/ecma_5/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/ecma_5/eval/browser.js
+++ b/js/src/tests/ecma_5/eval/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/extensions/browser.js
+++ b/js/src/tests/ecma_5/extensions/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/ecma_5/misc/browser.js
+++ b/js/src/tests/ecma_5/misc/browser.js
@@ -1,1 +0,0 @@
-
--- a/js/src/tests/js1_1/browser.js
+++ b/js/src/tests/js1_1/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/js1_1/shell.js
+++ b/js/src/tests/js1_1/shell.js
@@ -1,38 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
-
--- a/js/src/tests/js1_2/browser.js
+++ b/js/src/tests/js1_2/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/js1_2/shell.js
+++ b/js/src/tests/js1_2/shell.js
@@ -1,39 +0,0 @@
-/* -*- 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/
- *
- * 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
-
--- a/js/src/tests/js1_2/version120/browser.js
+++ b/js/src/tests/js1_2/version120/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/js1_3/browser.js
+++ b/js/src/tests/js1_3/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/js1_3/shell.js
+++ b/js/src/tests/js1_3/shell.js
@@ -1,39 +0,0 @@
-/* -*- 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/
- *
- * 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
-
--- a/js/src/tests/js1_4/browser.js
+++ b/js/src/tests/js1_4/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/js1_4/shell.js
+++ b/js/src/tests/js1_4/shell.js
@@ -1,38 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
-
--- a/js/src/tests/js1_5/browser.js
+++ b/js/src/tests/js1_5/browser.js
@@ -1,37 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/js1_5/decompilation/shell.js
+++ b/js/src/tests/js1_5/decompilation/shell.js
@@ -1,1 +0,0 @@
- 
--- a/js/src/tests/js1_5/shell.js
+++ b/js/src/tests/js1_5/shell.js
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
-
--- a/js/src/tests/js1_6/browser.js
+++ b/js/src/tests/js1_6/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/js1_6/shell.js
+++ b/js/src/tests/js1_6/shell.js
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
-
--- a/js/src/tests/js1_7/browser.js
+++ b/js/src/tests/js1_7/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/js1_8/browser.js
+++ b/js/src/tests/js1_8/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/tests/js1_8_1/browser.js
+++ b/js/src/tests/js1_8_1/browser.js
@@ -1,36 +0,0 @@
-/* -*- 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/
- *
- * 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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 ***** */
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2158,17 +2158,17 @@ SetScriptReferent(JSObject *obj, JSScrip
 
 static void
 DebuggerScript_trace(JSTracer *trc, JSObject *obj)
 {
     if (!trc->runtime->gcCurrentCompartment) {
         /* This comes from a private pointer, so no barrier needed. */
         if (JSScript *script = GetScriptReferent(obj)) {
             MarkScriptUnbarriered(trc, &script, "Debugger.Script referent");
-            SetScriptReferent(obj, script);
+            obj->setPrivateUnbarriered(script);
         }
     }
 }
 
 Class DebuggerScript_class = {
     "Script",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGSCRIPT_COUNT),
--- a/js/xpconnect/src/Makefile.in
+++ b/js/xpconnect/src/Makefile.in
@@ -167,34 +167,34 @@ dombindings_gen.h: $(srcdir)/dombindings
                    $(topsrcdir)/xpcom/idl-parser/header.py \
                    $(topsrcdir)/xpcom/idl-parser/xpidl.py \
                    $(DEPTH)/js/src/js-confdefs.h
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(srcdir)/dombindingsgen.py \
 	  --idlpath=$(DEPTH)/dist/idl \
-	  --cachedir=$(DEPTH)/xpcom/idl-parser/cache \
+	  --cachedir=$(DEPTH)/xpcom/idl-parser \
 	  --header-output dombindings_gen.h \
 	  $(srcdir)/dombindings.conf
 
 exports:: dombindings_gen.h
 
 dombindings_gen.cpp: $(srcdir)/dombindings.conf \
                      $(srcdir)/dombindingsgen.py \
                      $(srcdir)/codegen.py \
                      $(topsrcdir)/xpcom/idl-parser/header.py \
                      $(topsrcdir)/xpcom/idl-parser/xpidl.py \
                      $(DEPTH)/js/src/js-confdefs.h
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(srcdir)/dombindingsgen.py \
 	  --idlpath=$(DEPTH)/dist/idl \
-	  --cachedir=$(DEPTH)/xpcom/idl-parser/cache \
+	  --cachedir=$(DEPTH)/xpcom/idl-parser \
 	  --stub-output dombindings_gen.cpp \
 	  --makedepend-output $(MDDEPDIR)/dombindingsgen.pp \
 	  $(srcdir)/dombindings.conf
 
 DictionaryHelpers.$(OBJ_SUFFIX): DictionaryHelpers.h \
                                  DictionaryHelpers.cpp
 
 DictionaryHelpers.h: $(srcdir)/dictionary_helper_gen.conf \
@@ -203,32 +203,32 @@ DictionaryHelpers.h: $(srcdir)/dictionar
                      $(topsrcdir)/xpcom/idl-parser/header.py \
                      $(topsrcdir)/xpcom/idl-parser/xpidl.py \
                      $(DEPTH)/js/src/js-confdefs.h
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(srcdir)/dictionary_helper_gen.py \
 	  -I $(DEPTH)/dist/idl \
-	  --cachedir=$(DEPTH)/xpcom/idl-parser/cache \
+	  --cachedir=$(DEPTH)/xpcom/idl-parser \
 	  --header-output DictionaryHelpers.h \
 	  $(srcdir)/dictionary_helper_gen.conf
 
 DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \
                        $(srcdir)/dictionary_helper_gen.py \
                        $(srcdir)/codegen.py \
                        $(topsrcdir)/xpcom/idl-parser/header.py \
                        $(topsrcdir)/xpcom/idl-parser/xpidl.py \
                        $(DEPTH)/js/src/js-confdefs.h
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(srcdir)/dictionary_helper_gen.py \
 	  -I $(DEPTH)/dist/idl \
-	  --cachedir=$(DEPTH)/xpcom/idl-parser/cache \
+	  --cachedir=$(DEPTH)/xpcom/idl-parser \
 	  --header-output DictionaryHelpers.h \
 	  --stub-output DictionaryHelpers.cpp \
 	  --makedepend-output $(MDDEPDIR)/dictionary_helper_gen.pp \
 	  $(srcdir)/dictionary_helper_gen.conf
 
 _EXTRA_EXPORT_FILES = \
   DictionaryHelpers.h \
   $(NULL)
@@ -243,14 +243,11 @@ GARBAGE += \
 		dombindings_gen.cpp \
 		DictionaryHelpers.h \
 		DictionaryHelpers.cpp \
 		xpidl_debug \
 		$(MDDEPDIR)/dom_qsgen.pp \
 		$(MDDEPDIR)/dombindingsgen.pp \
 		$(MDDEPDIR)/dictionary_helper_gen.pp \
 		$(wildcard $(topsrcdir)/other-licenses/ply/ply/*.pyc) \
-		$(wildcard $(topsrcdir)/xpcom/idl-parser/*.pyc) \
 		$(NULL)
 
-GARBAGE_DIRS += $(DEPTH)/xpcom/idl-parser/cache
-
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -135,18 +135,16 @@ abstract public class GeckoApp
     private BroadcastReceiver mConnectivityReceiver;
     private BroadcastReceiver mBatteryReceiver;
 
     public static BrowserToolbar mBrowserToolbar;
     public static DoorHangerPopup mDoorHangerPopup;
     public static FormAssistPopup mFormAssistPopup;
     public Favicons mFavicons;
 
-    private Geocoder mGeocoder;
-    private Address  mLastGeoAddress;
     private static LayerController mLayerController;
     private static PlaceholderLayerClient mPlaceholderLayerClient;
     private static GeckoLayerClient mLayerClient;
     private AboutHomeContent mAboutHomeContent;
     private static AbsoluteLayout mPluginContainer;
 
     public String mLastTitle;
     public String mLastSnapshotUri;
@@ -2606,69 +2604,32 @@ abstract public class GeckoApp
     }
 
     public GeckoLayerClient getLayerClient() { return mLayerClient; }
     public LayerController getLayerController() { return mLayerController; }
 
     // accelerometer
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
+        Log.w(LOGTAG, "onAccuracyChanged "+accuracy);
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorAccuracyEvent(accuracy));
     }
 
     public void onSensorChanged(SensorEvent event)
     {
         Log.w(LOGTAG, "onSensorChanged "+event);
         GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event));
     }
 
-    private class GeocoderRunnable implements Runnable {
-        Location mLocation;
-        GeocoderRunnable (Location location) {
-            mLocation = location;
-        }
-        public void run() {
-            try {
-                List<Address> addresses = mGeocoder.getFromLocation(mLocation.getLatitude(),
-                                                                    mLocation.getLongitude(), 1);
-                // grab the first address.  in the future,
-                // may want to expose multiple, or filter
-                // for best.
-                mLastGeoAddress = addresses.get(0);
-                GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(mLocation, mLastGeoAddress));
-            } catch (Exception e) {
-                Log.w(LOGTAG, "GeocoderTask "+e);
-            }
-        }
-    }
-
     // geolocation
     public void onLocationChanged(Location location)
     {
         Log.w(LOGTAG, "onLocationChanged "+location);
-        if (mGeocoder == null)
-            mGeocoder = new Geocoder(mLayerController.getView().getContext(), Locale.getDefault());
-
-        if (mLastGeoAddress == null) {
-            GeckoAppShell.getHandler().post(new GeocoderRunnable(location));
-        }
-        else {
-            float[] results = new float[1];
-            Location.distanceBetween(location.getLatitude(),
-                                     location.getLongitude(),
-                                     mLastGeoAddress.getLatitude(),
-                                     mLastGeoAddress.getLongitude(),
-                                     results);
-            // pfm value.  don't want to slam the
-            // geocoder with very similar values, so
-            // only call after about 100m
-            if (results[0] > 100)
-                GeckoAppShell.getHandler().post(new GeocoderRunnable(location));
-        }
-
-        GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location, mLastGeoAddress));
+
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location));
     }
 
     public void onProviderDisabled(String provider)
     {
     }
 
     public void onProviderEnabled(String provider)
     {
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -121,16 +121,25 @@ public class GeckoAppShell
     /* Is the value in sVibrationEndTime valid? */
     private static boolean sVibrationMaybePlaying = false;
 
     /* Time (in System.nanoTime() units) when the currently-playing vibration
      * is scheduled to end.  This value is valid only when
      * sVibrationMaybePlaying is true. */
     private static long sVibrationEndTime = 0;
 
+    /* Default value of how fast we should hint the Android sensors. */
+    private static int sDefaultSensorHint = 100;
+
+    private static Sensor gAccelerometerSensor = null;
+    private static Sensor gLinearAccelerometerSensor = null;
+    private static Sensor gGyroscopeSensor = null;
+    private static Sensor gOrientationSensor = null;
+    private static Sensor gProximitySensor = null;
+
     /* The Android-side API: API methods that Android calls */
 
     // Initialization methods
     public static native void nativeInit();
     public static native void nativeRun(String args);
 
     // helper methods
     //    public static native void setSurfaceView(GeckoSurfaceView sv);
@@ -529,41 +538,16 @@ public class GeckoAppShell
 
     // Signal the Java thread that it's time to wake up
     public static void acknowledgeEventSync() {
         CountDownLatch tmp = sGeckoPendingAcks;
         if (tmp != null)
             tmp.countDown();
     }
 
-    static Sensor gAccelerometerSensor = null;
-    static Sensor gOrientationSensor = null;
-
-    public static void enableDeviceMotion(boolean enable) {
-        LayerView v = GeckoApp.mAppContext.getLayerController().getView();
-        SensorManager sm = (SensorManager) v.getContext().getSystemService(Context.SENSOR_SERVICE);
-
-        if (gAccelerometerSensor == null || gOrientationSensor == null) {
-            gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
-            gOrientationSensor   = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
-        }
-
-        if (enable) {
-            if (gAccelerometerSensor != null)
-                sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
-            if (gOrientationSensor != null)
-                sm.registerListener(GeckoApp.mAppContext, gOrientationSensor,   SensorManager.SENSOR_DELAY_GAME);
-        } else {
-            if (gAccelerometerSensor != null)
-                sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor);
-            if (gOrientationSensor != null)
-                sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor);
-        }
-    }
-
     public static void enableLocation(final boolean enable) {
         getMainHandler().post(new Runnable() { 
                 public void run() {
                     LocationManager lm = (LocationManager)
                         GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
 
                     if (enable) {
                         Criteria criteria = new Criteria();
@@ -579,46 +563,87 @@ public class GeckoAppShell
                         lm.requestLocationUpdates(provider, 100, (float).5, GeckoApp.mAppContext, l);
                     } else {
                         lm.removeUpdates(GeckoApp.mAppContext);
                     }
                 }
             });
     }
 
-    /*
-     * Keep these values consistent with |SensorType| in Hal.h
-     */
-    private static final int SENSOR_ORIENTATION = 1;
-    private static final int SENSOR_ACCELERATION = 2;
-    private static final int SENSOR_PROXIMITY = 3;
-
-    private static Sensor gProximitySensor = null;
-
     public static void enableSensor(int aSensortype) {
         SensorManager sm = (SensorManager)
             GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE);
 
         switch(aSensortype) {
-        case SENSOR_PROXIMITY:
+        case GeckoHalDefines.SENSOR_ORIENTATION:
+            if(gOrientationSensor == null)
+                gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+            if (gOrientationSensor != null)
+                sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint);
+            break;
+
+        case GeckoHalDefines.SENSOR_ACCELERATION:
+            if(gAccelerometerSensor == null)
+                gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+            if (gAccelerometerSensor != null)
+                sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint);
+            break;
+
+        case GeckoHalDefines.SENSOR_PROXIMITY:
             if(gProximitySensor == null)
                 gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
-            sm.registerListener(GeckoApp.mAppContext, gProximitySensor,
-                                SensorManager.SENSOR_DELAY_GAME);
+            if (gProximitySensor != null)
+                sm.registerListener(GeckoApp.mAppContext, gProximitySensor, sDefaultSensorHint);
             break;
+
+        case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION:
+            if(gLinearAccelerometerSensor == null)
+                gLinearAccelerometerSensor = sm.getDefaultSensor(10);
+            if (gLinearAccelerometerSensor != null)
+                sm.registerListener(GeckoApp.mAppContext, gLinearAccelerometerSensor, sDefaultSensorHint);
+            break;
+
+        case GeckoHalDefines.SENSOR_GYROSCOPE:
+            if(gGyroscopeSensor == null)
+                gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+            if (gGyroscopeSensor != null)
+                sm.registerListener(GeckoApp.mAppContext, gGyroscopeSensor, sDefaultSensorHint);
+            break;
+
         }
     }
 
     public static void disableSensor(int aSensortype) {
         SensorManager sm = (SensorManager)
             GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE);
 
-        switch(aSensortype) {
-        case SENSOR_PROXIMITY:
-            sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor);
+        switch (aSensortype) {
+        case GeckoHalDefines.SENSOR_ORIENTATION:
+            if (gOrientationSensor != null)
+                sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor);
+            break;
+
+        case GeckoHalDefines.SENSOR_ACCELERATION:
+            if (gAccelerometerSensor != null)
+                sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor);
+            break;
+
+        case GeckoHalDefines.SENSOR_PROXIMITY:
+            if (gProximitySensor != null)
+                sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor);
+            break;
+
+        case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION:
+            if (gLinearAccelerometerSensor != null)
+                sm.unregisterListener(GeckoApp.mAppContext, gLinearAccelerometerSensor);
+            break;
+
+        case GeckoHalDefines.SENSOR_GYROSCOPE:
+            if (gGyroscopeSensor != null)
+                sm.unregisterListener(GeckoApp.mAppContext, gGyroscopeSensor);
             break;
         }
     }
 
     public static void moveTaskToBack() {
         GeckoApp.mAppContext.moveTaskToBack(true);
     }
 
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -48,34 +48,35 @@ import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
 import android.util.FloatMath;
 import android.util.DisplayMetrics;
 import android.graphics.PointF;
 import android.text.format.Time;
 import android.os.SystemClock;
+import java.lang.Math;
 import java.lang.System;
 
 import android.util.Log;
 
 /* We're not allowed to hold on to most events given to us
  * so we save the parts of the events we want to use in GeckoEvent.
  * Fields have different meanings depending on the event type.
  */
 
 public class GeckoEvent {
     private static final String LOGTAG = "GeckoEvent";
 
     private static final int INVALID = -1;
     private static final int NATIVE_POKE = 0;
     private static final int KEY_EVENT = 1;
     private static final int MOTION_EVENT = 2;
-    private static final int ORIENTATION_EVENT = 3;
-    private static final int ACCELERATION_EVENT = 4;
+    private static final int SENSOR_EVENT = 3;
+    private static final int UNUSED1_EVENT = 4;
     private static final int LOCATION_EVENT = 5;
     private static final int IME_EVENT = 6;
     private static final int DRAW = 7;
     private static final int SIZE_CHANGED = 8;
     private static final int ACTIVITY_STOPPING = 9;
     private static final int ACTIVITY_PAUSING = 10;
     private static final int ACTIVITY_SHUTDOWN = 11;
     private static final int LOAD_URI = 12;
@@ -85,16 +86,17 @@ public class GeckoEvent {
     private static final int ACTIVITY_START = 17;
     private static final int BROADCAST = 19;
     private static final int VIEWPORT = 20;
     private static final int VISITED = 21;
     private static final int NETWORK_CHANGED = 22;
     private static final int PROXIMITY_EVENT = 23;
     private static final int ACTIVITY_RESUMING = 24;
     private static final int SCREENSHOT = 25;
+    private static final int SENSOR_ACCURACY = 26;
 
     public static final int IME_COMPOSITION_END = 0;
     public static final int IME_COMPOSITION_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
     public static final int IME_SET_SELECTION = 5;
     public static final int IME_GET_SELECTION = 6;
@@ -116,17 +118,16 @@ public class GeckoEvent {
     public Point[] mPoints;
     public int[] mPointIndicies;
     public int mPointerIndex; // index of the point that has changed
     public float[] mOrientations;
     public float[] mPressures;
     public Point[] mPointRadii;
     public Rect mRect;
     public double mX, mY, mZ;
-    public double mAlpha, mBeta, mGamma;
     public double mDistance;
 
     public int mMetaState, mFlags;
     public int mKeyCode, mUnicodeChar;
     public int mOffset, mCount;
     public String mCharacters, mCharactersExtra;
     public int mRangeType, mRangeStyles;
     public int mRangeForeColor, mRangeBackColor;
@@ -275,46 +276,66 @@ public class GeckoEvent {
         } catch(Exception ex) {
             Log.e(LOGTAG, "Error creating motion point " + index, ex);
             mPointRadii[index] = new Point(0, 0);
             mPoints[index] = new Point(0, 0);
         }
     }
 
     public static GeckoEvent createSensorEvent(SensorEvent s) {
+        int sensor_type = s.sensor.getType();
         GeckoEvent event = null;
-        int sensor_type = s.sensor.getType();
- 
+
         switch(sensor_type) {
+
         case Sensor.TYPE_ACCELEROMETER:
-            event = new GeckoEvent(ACCELERATION_EVENT);
+            event = new GeckoEvent(SENSOR_EVENT);
+            event.mFlags = GeckoHalDefines.SENSOR_ACCELERATION;
+            event.mX = s.values[0];
+            event.mY = s.values[1];
+            event.mZ = s.values[2];
+            break;
+
+        case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ :
+            event = new GeckoEvent(SENSOR_EVENT);
+            event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION;
             event.mX = s.values[0];
             event.mY = s.values[1];
             event.mZ = s.values[2];
             break;
-            
+
         case Sensor.TYPE_ORIENTATION:
-            event = new GeckoEvent(ORIENTATION_EVENT);
-            event.mAlpha = -s.values[0];
-            event.mBeta = -s.values[1];
-            event.mGamma = -s.values[2];
+            event = new GeckoEvent(SENSOR_EVENT);
+            event.mFlags = GeckoHalDefines.SENSOR_ORIENTATION;
+            event.mX = s.values[0];
+            event.mY = s.values[1];
+            event.mZ = s.values[2];
+            break;
+
+        case Sensor.TYPE_GYROSCOPE:
+            event = new GeckoEvent(SENSOR_EVENT);
+            event.mFlags = GeckoHalDefines.SENSOR_GYROSCOPE;
+            event.mX = Math.toDegrees(s.values[0]);
+            event.mY = Math.toDegrees(s.values[1]);
+            event.mZ = Math.toDegrees(s.values[2]);
             break;
 
         case Sensor.TYPE_PROXIMITY:
+            // bug 734854 - maybe we can get rid of this event.  is
+            // values[1] and values[2] valid?
             event = new GeckoEvent(PROXIMITY_EVENT);
             event.mDistance = s.values[0];
             break;
         }
         return event;
     }
 
-    public static GeckoEvent createLocationEvent(Location l, Address a) {
+    public static GeckoEvent createLocationEvent(Location l) {
         GeckoEvent event = new GeckoEvent(LOCATION_EVENT);
         event.mLocation = l;
-        event.mAddress  = a;
         return event;
     }
 
     public static GeckoEvent createIMEEvent(int imeAction, int offset, int count) {
         GeckoEvent event = new GeckoEvent(IME_EVENT);
         event.mAction = imeAction;
         event.mOffset = offset;
         event.mCount = count;
@@ -411,9 +432,15 @@ public class GeckoEvent {
     public static GeckoEvent createScreenshotEvent(int tabId, int sw, int sh, int dw, int dh) {
         GeckoEvent event = new GeckoEvent(SCREENSHOT);
         event.mPoints = new Point[2];
         event.mPoints[0] = new Point(sw, sh);
         event.mPoints[1] = new Point(dw, dh);
         event.mMetaState = tabId;
         return event;
     }
+
+    public static GeckoEvent createSensorAccuracyEvent(int accuracy) {
+        GeckoEvent event = new GeckoEvent(SENSOR_ACCURACY);
+        event.mFlags = accuracy;
+        return event;
+    }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/GeckoHalDefines.java
@@ -0,0 +1,49 @@
+/* -*- 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) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+package org.mozilla.gecko;
+
+public class GeckoHalDefines
+{
+    /*
+     * Keep these values consistent with |SensorType| in Hal.h
+    */
+    public static final int SENSOR_ORIENTATION = 0;
+    public static final int SENSOR_ACCELERATION = 1;
+    public static final int SENSOR_PROXIMITY = 2;
+    public static final int SENSOR_LINEAR_ACCELERATION = 3;
+    public static final int SENSOR_GYROSCOPE = 4;
+};
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -82,16 +82,17 @@ FENNEC_JAVA_FILES = \
   GeckoAppShell.java \
   GeckoAsyncTask.java \
   GeckoBatteryManager.java \
   GeckoBackgroundThread.java \
   GeckoConnectivityReceiver.java \
   GeckoEvent.java \
   GeckoEventListener.java \
   GeckoEventResponder.java \
+  GeckoHalDefines.java \
   GeckoInputConnection.java \
 	GeckoMessageReceiver.java \
   GeckoPreferences.java \
   GeckoProfile.java \
   GeckoStateListDrawable.java \
   GeckoThread.java \
   GlobalHistory.java \
   LinkPreference.java \
@@ -230,16 +231,17 @@ ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
 DEFINES += -DMOZ_ANDROID_SHARED_ID="$(ANDROID_PACKAGE_NAME).sharedID"
 endif
 
 RES_LAYOUT = \
   $(SYNC_RES_LAYOUT) \
   res/layout/autocomplete_list_item.xml \
   res/layout/awesomebar.xml \
+  res/layout/awesomebar_actionbar.xml \
   res/layout/awesomebar_folder_row.xml \
   res/layout/awesomebar_folder_header_row.xml \
   res/layout/awesomebar_header_row.xml \
   res/layout/awesomebar_row.xml \
   res/layout/awesomebar_search.xml \
   res/layout/awesomebar_tab_indicator.xml \
   res/layout/awesomebar_tabs.xml \
   res/layout/bookmark_edit.xml \
--- a/mobile/android/base/TabsTray.java
+++ b/mobile/android/base/TabsTray.java
@@ -1,44 +1,12 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Sriram Ramasubramanian <sriram@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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import java.util.ArrayList;
 
 import android.accounts.AccountManager;
 import android.app.Activity;
 import android.content.Context;
@@ -55,16 +23,18 @@ import android.widget.BaseAdapter;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import org.mozilla.gecko.sync.setup.SyncAccounts;
+
 public class TabsTray extends Activity implements Tabs.OnTabsChangedListener {
 
     private static int sPreferredHeight;
     private static int sMaxHeight;
     private static int sListItemHeight;
     private static int sAddTabHeight;
     private static ListView mList;
     private static TabsListContainer mListContainer;
@@ -117,29 +87,33 @@ public class TabsTray extends Activity i
         sPreferredHeight = (int) (0.67 * metrics.heightPixels);
         sMaxHeight = (int) (sPreferredHeight + (0.33 * sListItemHeight));
 
         Tabs tabs = Tabs.getInstance();
         tabs.registerOnTabsChangedListener(this);
         tabs.refreshThumbnails();
         onTabChanged(null, null);
 
-         // If sync is set up, query the database for remote clients
-         // Cleanup after Bug: 734211 is fixed
-         if (AccountManager.get(getApplicationContext()).getAccountsByType("org.mozilla.firefox_sync").length > 0) {
-             TabsAccessor.areClientsAvailable(getApplicationContext(), new TabsAccessor.OnClientsAvailableListener() {
-                 @Override
-                 public void areAvailable(boolean available) {
-                     if (available)
-                         mRemoteTabs.setVisibility(View.VISIBLE);
-                     else
-                         mRemoteTabs.setVisibility(View.GONE);
-                 }
-             });
-        }
+        // If Sync is set up, query the database for remote clients.
+        final Context context = getApplicationContext();
+        new SyncAccounts.AccountsExistTask() {
+            @Override
+            protected void onPostExecute(Boolean result) {
+                if (!result.booleanValue()) {
+                    return;
+                }
+                TabsAccessor.areClientsAvailable(context, new TabsAccessor.OnClientsAvailableListener() {
+                    @Override
+                    public void areAvailable(boolean available) {
+                        final int visibility = available ? View.VISIBLE : View.GONE;
+                        mRemoteTabs.setVisibility(visibility);
+                    }
+                });
+            }
+        }.execute(context);
     }
 
     @Override
     public void onDestroy() {
         super.onDestroy();
         Tabs.getInstance().unregisterOnTabsChangedListener(this);
     }
 
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/awesomebar_actionbar.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              style="@style/AddressBar"/>
--- a/mobile/android/base/resources/values-v11/styles.xml
+++ b/mobile/android/base/resources/values-v11/styles.xml
@@ -34,16 +34,18 @@
     <style name="ActionBar.GeckoApp">
          <item name="android:background">@drawable/gecko_actionbar_bg</item>
          <item name="android:displayOptions">showCustom</item>
          <item name="android:customNavigationLayout">@layout/browser_toolbar</item>
     </style>
 
     <!-- AwesomeBar ActionBar -->
     <style name="ActionBar.AwesomeBar">
+         <item name="android:displayOptions">showCustom</item>
+         <item name="android:customNavigationLayout">@layout/awesomebar_actionbar</item>
          <item name="android:visibility">gone</item>
     </style>
  
     <!-- GeckoPreferences ActionBar -->
     <style name="ActionBar.GeckoPreferences">
          <item name="android:displayOptions">showHome|homeAsUp|showTitle</item>
     </style>
  
--- a/mobile/android/base/sync/repositories/RepositorySession.java
+++ b/mobile/android/base/sync/repositories/RepositorySession.java
@@ -1,45 +1,11 @@
-/* ***** 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 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):
- * Jason Voll <jvoll@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
- * 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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.repositories;
 
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -48,26 +14,32 @@ import org.mozilla.gecko.sync.repositori
 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate;
 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate;
 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionGuidsSinceDelegate;
 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate;
 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate;
 import org.mozilla.gecko.sync.repositories.domain.Record;
 
 /**
- * A RepositorySession is created and used thusly:
+ * A <code>RepositorySession</code> is created and used thusly:
  *
- * * Construct, with a reference to its parent Repository, by calling
- *   Repository.createSession().
- * * Populate with saved information by calling unbundle().
- * * Begin a sync by calling begin().
- * * Perform operations such as fetchSince() and store().
- * * Finish by calling finish(), retrieving and storing the current bundle.
+ *<ul>
+ * <li>Construct, with a reference to its parent {@link Repository}, by calling
+ *   {@link Repository#createSession(RepositorySessionCreationDelegate, android.content.Context)}.</li>
+ * <li>Populate with saved information by calling {@link #unbundle(RepositorySessionBundle)}.</li>
+ * <li>Begin a sync by calling {@link #begin(RepositorySessionBeginDelegate)}. <code>begin()</code>
+ *   is an appropriate place to initialize expensive resources.</li>
+ * <li>Perform operations such as {@link #fetchSince(long, RepositorySessionFetchRecordsDelegate)} and
+ *   {@link #store(Record)}.</li>
+ * <li>Finish by calling {@link #finish(RepositorySessionFinishDelegate)}, retrieving and storing
+ *   the current bundle.</li>
+ *</ul>
  *
- * @author rnewman
+ * If <code>finish()</code> is not called, {@link #abort()} must be called. These calls must
+ * <em>always</em> be paired with <code>begin()</code>.
  *
  */
 public abstract class RepositorySession {
 
   public enum SessionStatus {
     UNSTARTED,
     ACTIVE,
     ABORTED,
@@ -187,16 +159,23 @@ public abstract class RepositorySession 
       throw new InvalidSessionTransitionException(null);
     }
     if (storeWorkQueue.isShutdown()) {
       throw new InvalidSessionTransitionException(null);
     }
     this.transitionFrom(SessionStatus.UNSTARTED, SessionStatus.ACTIVE);
   }
 
+  /**
+   * Start the session. This is an appropriate place to initialize
+   * data access components such as database handles.
+   *
+   * @param delegate
+   * @throws InvalidSessionTransitionException
+   */
   public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
     sharedBegin();
     delegate.deferredBeginDelegate(delegateQueue).onBeginSucceeded(this);
   }
 
   protected RepositorySessionBundle getBundle() {
     return this.getBundle(null);
   }
@@ -223,31 +202,42 @@ public abstract class RepositorySession 
    * Just like finish(), but doesn't do any work that should only be performed
    * at the end of a successful sync, and can be called any time.
    */
   public void abort(RepositorySessionFinishDelegate delegate) {
     this.abort();
     delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
   }
 
+  /**
+   * Abnormally terminate the repository session, freeing or closing
+   * any resources that were opened during the lifetime of the session.
+   */
   public void abort() {
     // TODO: do something here.
     this.setStatus(SessionStatus.ABORTED);
     try {
       storeWorkQueue.shutdown();
     } catch (Exception e) {
       Logger.error(LOG_TAG, "Caught exception shutting down store work queue.", e);
     }
     try {
       delegateQueue.shutdown();
     } catch (Exception e) {
       Logger.error(LOG_TAG, "Caught exception shutting down delegate queue.", e);
     }
   }
 
+  /**
+   * End the repository session, freeing or closing any resources
+   * that were opened during the lifetime of the session.
+   *
+   * @param delegate notified of success or failure.
+   * @throws InactiveSessionException
+   */
   public void finish(final RepositorySessionFinishDelegate delegate) throws InactiveSessionException {
     try {
       this.transitionFrom(SessionStatus.ACTIVE, SessionStatus.DONE);
       delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
     } catch (InvalidSessionTransitionException e) {
       Logger.error(LOG_TAG, "Tried to finish() an unstarted or already finished session");
       InactiveSessionException ex = new InactiveSessionException(null);
       ex.initCause(e);
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java
+++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java
@@ -454,31 +454,31 @@ public class AndroidBrowserBookmarksRepo
       return null;
     }
 
     Logger.debug(LOG_TAG, "Fetched " + childArray.size() + " children for " + recordGUID);
     return childArray;
   }
 
   @Override
-  protected boolean checkRecordType(Record record) {
+  protected boolean shouldIgnore(Record record) {
     if (!(record instanceof BookmarkRecord)) {
-      return false;
+      return true;
     }
     if (record.deleted) {
-      return true;
+      return false;
     }
     BookmarkRecord bmk = (BookmarkRecord) record;
 
     if (bmk.isBookmark() ||
         bmk.isFolder()) {
-      return true;
+      return false;
     }
     Logger.info(LOG_TAG, "Ignoring record with guid: " + bmk.guid + " and type: " + bmk.type);
-    return false;
+    return true;
   }
   
   @Override
   public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
     // Check for the existence of special folders
     // and insert them if they don't exist.
     Cursor cur;
     try {
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java
+++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java
@@ -1,45 +1,11 @@
-/* ***** 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 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):
- *   Jason Voll <jvoll@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
- * 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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.repositories.android;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.repositories.InactiveSessionException;
@@ -113,19 +79,23 @@ public abstract class AndroidBrowserRepo
    * of a folder might be repositioned as we generate the folder's record.
    *
    * @throws NoGuidForIdException
    * @throws NullCursorException
    * @throws ParentNotFoundException
    */
   protected abstract Record retrieveDuringFetch(Cursor cur) throws NoGuidForIdException, NullCursorException, ParentNotFoundException;
 
-  // Must be overriden by AndroidBookmarkRepositorySession.
-  protected boolean checkRecordType(Record record) {
-    return true;
+  /**
+   * Override this to allow records to be skipped during insertion.
+   *
+   * For example, a session subclass might skip records of an unsupported type.
+   */
+  protected boolean shouldIgnore(Record record) {
+    return false;
   }
 
   /**
    * Override in subclass to implement record extension.
    * Return null if this record should not be processed.
    *
    * @param record
    *        The record to transform. Can be null.
@@ -388,18 +358,18 @@ public abstract class AndroidBrowserRepo
           return;
         }
 
         // Check that the record is a valid type.
         // Fennec only supports bookmarks and folders. All other types of records,
         // including livemarks and queries, are simply ignored.
         // See Bug 708149. This might be resolved by Fennec changing its database
         // schema, or by Sync storing non-applied records in its own private database.
-        if (!checkRecordType(record)) {
-          Logger.debug(LOG_TAG, "Ignoring record " + record.guid + " due to unknown record type.");
+        if (shouldIgnore(record)) {
+          Logger.debug(LOG_TAG, "Ignoring record " + record.guid);
 
           // Don't throw: we don't want to abort the entire sync when we get a livemark!
           // delegate.onRecordStoreFailed(new InvalidBookmarkTypeException(null));
           return;
         }
 
 
         // TODO: lift these into the session.
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/sync/setup/SyncAccounts.java
@@ -0,0 +1,120 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.sync.setup;
+
+import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.Utils;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * This class contains utilities that are of use to Fennec
+ * and Sync setup activities.
+ *
+ * Do not break these APIs without correcting upstream code!
+ */
+public class SyncAccounts {
+
+  private final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/";
+  private static final String LOG_TAG = "SyncAccounts";
+
+  /**
+   * Returns true if a Sync account is set up.
+   *
+   * Do not call this method from the main thread.
+   */
+  public static boolean syncAccountsExist(Context c) {
+    return AccountManager.get(c).getAccountsByType("org.mozilla.firefox_sync").length > 0;
+  }
+
+  /**
+   * This class provides background-thread abstracted access to whether a
+   * Firefox Sync account has been set up on this device.
+   *
+   * Subclass this task and override `onPostExecute` to act on the result.
+   */
+  public static class AccountsExistTask extends AsyncTask<Context, Void, Boolean> {
+    @Override
+    protected Boolean doInBackground(Context... params) {
+      Context c = params[0];
+      return syncAccountsExist(c);
+    }
+  }
+
+  public static Intent createAccount(Context context,
+                                     AccountManager accountManager,
+                                     String username,
+                                     String syncKey,
+                                     String password,
+                                     String serverURL) {
+
+    final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC);
+    final Bundle userbundle = new Bundle();
+
+    // Add sync key and server URL.
+    userbundle.putString(Constants.OPTION_SYNCKEY, syncKey);
+    if (serverURL != null) {
+      Logger.info(LOG_TAG, "Setting explicit server URL: " + serverURL);
+      userbundle.putString(Constants.OPTION_SERVER, serverURL);
+    } else {
+      userbundle.putString(Constants.OPTION_SERVER, DEFAULT_SERVER);
+    }
+    Logger.debug(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC);
+    boolean result = false;
+    try {
+      result = accountManager.addAccountExplicitly(account, password, userbundle);
+    } catch (SecurityException e) {
+      final String message = e.getMessage();
+      if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) {
+        Log.wtf("FirefoxSync",
+                "Unable to create account. " +
+                "If you have more than one version of " +
+                "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.",
+                e);
+      } else {
+        Log.e("FirefoxSync", "Unable to create account.", e);
+      }
+    }
+
+    Logger.debug(LOG_TAG, "Account: " + account + " added successfully? " + result);
+    if (!result) {
+      Logger.error(LOG_TAG, "Failed to add account!");
+    }
+
+    // Set components to sync (default: all).
+    ContentResolver.setMasterSyncAutomatically(true);
+
+    String authority = BrowserContract.AUTHORITY;
+    Logger.debug(LOG_TAG, "Setting authority " + authority + " to sync automatically.");
+    ContentResolver.setSyncAutomatically(account, authority, true);
+    ContentResolver.setIsSyncable(account, authority, 1);
+
+    // TODO: add other ContentProviders as needed (e.g. passwords)
+    // TODO: for each, also add to res/xml to make visible in account settings
+    Logger.debug(LOG_TAG, "Finished setting syncables.");
+
+    // TODO: correctly implement Sync Options.
+    Logger.info(LOG_TAG, "Clearing preferences for this account.");
+    try {
+      Utils.getSharedPreferences(context, username, serverURL).edit().clear().commit();
+    } catch (Exception e) {
+      Logger.error(LOG_TAG, "Could not clear prefs path!", e);
+    }
+
+    final Intent intent = new Intent();
+    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, username);
+    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
+    intent.putExtra(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
+    return intent;
+  }
+}
--- a/mobile/android/base/sync/setup/activities/AccountActivity.java
+++ b/mobile/android/base/sync/setup/activities/AccountActivity.java
@@ -2,42 +2,37 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup.activities;
 
 import java.util.Locale;
 
 import org.mozilla.gecko.R;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.setup.Constants;
+import org.mozilla.gecko.sync.setup.SyncAccounts;
 
-import android.accounts.Account;
 import android.accounts.AccountAuthenticatorActivity;
 import android.accounts.AccountManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.EditText;
 
 public class AccountActivity extends AccountAuthenticatorActivity {
   private final static String LOG_TAG        = "AccountActivity";
 
-  private final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/";
-
   private AccountManager      mAccountManager;
   private Context             mContext;
   private String              username;
   private String              password;
   private String              key;
   private String              server;
 
   // UI elements.
@@ -151,32 +146,34 @@ public class AccountActivity extends Acc
 
       @Override
       public void onTextChanged(CharSequence s, int start, int before, int count) {
       }
     };
   }
 
   private boolean validateInputs() {
-    if (usernameInput.length() == 0 || passwordInput.length() == 0
-        || synckeyInput.length() == 0
-        || (serverCheckbox.isChecked() && serverInput.length() == 0)) {
+    if (usernameInput.length() == 0 ||
+        passwordInput.length() == 0 ||
+        synckeyInput.length() == 0  ||
+        (serverCheckbox.isChecked() &&
+         serverInput.length() == 0)) {
       return false;
     }
     return true;
   }
 
   /*
    * Callback that handles auth based on success/failure
    */
   private void authCallback() {
     // Create and add account to AccountManager
     // TODO: only allow one account to be added?
     Log.d(LOG_TAG, "Using account manager " + mAccountManager);
-    final Intent intent = createAccount(mContext, mAccountManager,
+    final Intent intent = SyncAccounts.createAccount(mContext, mAccountManager,
                                         username,
                                         key, password, server);
     setAccountAuthenticatorResult(intent.getExtras());
 
     // Testing out the authFailure case
     // authFailure();
 
     // TODO: Currently, we do not actually authenticate username/pass against
@@ -188,84 +185,16 @@ public class AccountActivity extends Acc
     runOnUiThread(new Runnable() {
       @Override
       public void run() {
         authSuccess();
       }
     });
   }
 
-  // TODO: lift this out.
-  public static Intent createAccount(Context context,
-                                     AccountManager accountManager,
-                                     String username,
-                                     String syncKey,
-                                     String password,
-                                     String serverURL) {
-
-    final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC);
-    final Bundle userbundle = new Bundle();
-
-    // Add sync key and server URL.
-    userbundle.putString(Constants.OPTION_SYNCKEY, syncKey);
-    if (serverURL != null) {
-      Log.i(LOG_TAG, "Setting explicit server URL: " + serverURL);
-      userbundle.putString(Constants.OPTION_SERVER, serverURL);
-    } else {
-      userbundle.putString(Constants.OPTION_SERVER, DEFAULT_SERVER);
-    }
-    Log.d(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC);
-    boolean result = false;
-    try {
-      result = accountManager.addAccountExplicitly(account, password, userbundle);
-    } catch (SecurityException e) {
-      final String message = e.getMessage();
-      if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) {
-        Log.wtf("FirefoxSync",
-                "Unable to create account. " +
-                "If you have more than one version of " +
-                "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.",
-                e);
-      } else {
-        Log.e("FirefoxSync", "Unable to create account.", e);
-      }
-    }
-
-    Log.d(LOG_TAG, "Account: " + account + " added successfully? " + result);
-    if (!result) {
-      Log.e(LOG_TAG, "Failed to add account!");
-    }
-
-    // Set components to sync (default: all).
-    ContentResolver.setMasterSyncAutomatically(true);
-
-    String authority = BrowserContract.AUTHORITY;
-    Log.d(LOG_TAG, "Setting authority " + authority + " to sync automatically.");
-    ContentResolver.setSyncAutomatically(account, authority, true);
-    ContentResolver.setIsSyncable(account, authority, 1);
-
-    // TODO: add other ContentProviders as needed (e.g. passwords)
-    // TODO: for each, also add to res/xml to make visible in account settings
-    Log.d(LOG_TAG, "Finished setting syncables.");
-
-    // TODO: correctly implement Sync Options.
-    Log.i(LOG_TAG, "Clearing preferences for this account.");
-    try {
-      Utils.getSharedPreferences(context, username, serverURL).edit().clear().commit();
-    } catch (Exception e) {
-      Log.e(LOG_TAG, "Could not clear prefs path!", e);
-    }
-
-    final Intent intent = new Intent();
-    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, username);
-    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
-    intent.putExtra(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
-    return intent;
-  }
-
   @SuppressWarnings("unused")
   private void authFailure() {
     enableCredEntry(true);
     Intent intent = new Intent(mContext, SetupFailureActivity.class);
     intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
     startActivity(intent);
   }
 
--- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
@@ -8,16 +8,17 @@ import java.util.HashMap;
 
 import org.json.simple.JSONObject;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.ThreadPool;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.jpake.JPakeNoActivePairingException;
 import org.mozilla.gecko.sync.setup.Constants;
+import org.mozilla.gecko.sync.setup.SyncAccounts;
 
 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;
@@ -357,17 +358,17 @@ public class SetupSyncActivity extends A
   public void onComplete(JSONObject jCreds) {
     if (!pairWithPin) {
       String accountName  = (String) jCreds.get(Constants.JSON_KEY_ACCOUNT);
       String password     = (String) jCreds.get(Constants.JSON_KEY_PASSWORD);
       String syncKey      = (String) jCreds.get(Constants.JSON_KEY_SYNCKEY);
       String serverURL    = (String) jCreds.get(Constants.JSON_KEY_SERVER);
 
       Logger.debug(LOG_TAG, "Using account manager " + mAccountManager);
-      final Intent intent = AccountActivity.createAccount(mContext, mAccountManager,
+      final Intent intent = SyncAccounts.createAccount(mContext, mAccountManager,
                                                           accountName,
                                                           syncKey, password, serverURL);
       setAccountAuthenticatorResult(intent.getExtras());
 
       setResult(RESULT_OK, intent);
     }
 
     jClient = null; // Sync is set up. Kill reference to JPakeClient object.
--- a/mobile/android/chrome/Makefile.in
+++ b/mobile/android/chrome/Makefile.in
@@ -42,12 +42,9 @@ VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(MOZ_UI_LOCALE) \
            -DPACKAGE=browser \
            -DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
            $(NULL)
 
-
-TEST_DIRS += tests
-
 include $(topsrcdir)/config/rules.mk
--- a/mobile/android/chrome/content/bindings.xml
+++ b/mobile/android/chrome/content/bindings.xml
@@ -104,43 +104,16 @@
           // Just forward the menuitem command events, which the toolkit version does.
           if (event.target.parentNode.parentNode != this)
             event.stopPropagation();
         ]]>
       </handler>
     </handlers>
   </binding>
 
-  <binding id="chrome-select-option">
-    <content orient="horizontal" flex="1">
-      <xul:image class="chrome-select-option-image" anonid="check"/>
-      <xul:label anonid="label" xbl:inherits="value=label"/>
-    </content>
-
-    <implementation>
-      <property name="selected">
-        <getter>
-          <![CDATA[
-            return this.hasAttribute("selected");
-          ]]>
-        </getter>
-        <setter>
-          <![CDATA[
-            if (val)
-              this.setAttribute("selected", "true");
-            else
-              this.removeAttribute("selected");
-            return val;
-          ]]>
-        </setter>
-      </property>
-    </implementation>
-  </binding>
-
-
   <binding id="textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
     <handlers>
       <handler event="TapLong" phase="capturing">
         <![CDATA[
           let box = this.inputField.parentNode;
           box.showContextMenu(this, false);
         ]]>
       </handler>
@@ -256,75 +229,9 @@
             }
           }
 
           ContextHelper.showPopup({ target: aTextbox, json: json });
         ]]></body>
       </method>
     </implementation>
   </binding>
-  
-  <binding id="setting-fulltoggle-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-bool">
-    <handlers>
-      <handler event="click" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="command" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="TapSingle" button="0" phase="capturing">
-        <![CDATA[
-        this.input.setChecked(!this.value);
-        this.inputChanged();
-        this.fireEvent("oncommand");
-        ]]>
-      </handler>
-    </handlers>
-  </binding>
-
-  <binding id="setting-fulltoggle-boolint" extends="chrome://mozapps/content/extensions/setting.xml#setting-boolint">
-    <handlers>
-      <handler event="click" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="command" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="TapSingle" button="0" phase="capturing">
-        <![CDATA[
-        this.input.setChecked(!this.value);
-        this.inputChanged();
-        this.fireEvent("oncommand");
-        ]]>
-      </handler>
-    </handlers>
-  </binding>
-
-  <binding id="setting-fulltoggle-localized-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-localized-bool">
-    <handlers>
-      <handler event="click" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="command" button="0" phase="capturing">
-        <![CDATA[
-        event.stopPropagation();
-        ]]>
-      </handler>
-      <handler event="TapSingle" button="0" phase="capturing">
-        <![CDATA[
-        this.input.setChecked(!this.value);
-        this.inputChanged();
-        this.fireEvent("oncommand");
-        ]]>
-      </handler>
-    </handlers>
-  </binding>
 </bindings>
new file mode 100644
--- /dev/null
+++ b/mobile/android/chrome/content/bindings/settings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+
+<bindings
+    xmlns="http://www.mozilla.org/xbl"
+    xmlns:xbl="http://www.mozilla.org/xbl"
+    xmlns:html="http://www.w3.org/1999/xhtml"
+    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <binding id="setting-fulltoggle-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-bool">
+    <handlers>
+      <handler event="command" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        ]]>
+      </handler>
+      <handler event="click" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        this.input.checked = !this.input.checked;
+        this.inputChanged();
+        this.fireEvent("oncommand");
+        ]]>
+      </handler>
+    </handlers>
+  </binding>
+
+  <binding id="setting-fulltoggle-boolint" extends="chrome://mozapps/content/extensions/setting.xml#setting-boolint">
+    <handlers>
+      <handler event="command" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        ]]>
+      </handler>
+      <handler event="click" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        this.input.checked = !this.input.checked;
+        this.inputChanged();
+        this.fireEvent("oncommand");
+        ]]>
+      </handler>
+    </handlers>
+  </binding>
+
+  <binding id="setting-fulltoggle-localized-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-localized-bool">
+    <handlers>
+      <handler event="command" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        ]]>
+      </handler>
+      <handler event="click" button="0" phase="capturing">
+        <![CDATA[
+        event.stopPropagation();
+        this.input.checked = !this.input.checked;
+        this.inputChanged();
+        this.fireEvent("oncommand");
+        ]]>
+      </handler>
+    </handlers>
+  </binding>
+</bindings>
--- a/mobile/android/chrome/content/browser.css
+++ b/mobile/android/chrome/content/browser.css
@@ -1,66 +1,20 @@
-settings {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings");
-}
-
-setting[type="bool"] {
-  -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-bool");
-}
-
-setting[type="bool"][localized="true"] {
-  -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-localized-bool");
-}
-
-setting[type="boolint"] {
-  -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-boolint");
-}
-
-setting[type="integer"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-integer");
-}
-
-setting[type="control"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-control");
-}
-
-setting[type="string"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-string");
-}
-
-setting[type="color"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-color");
-}
-
-setting[type="file"],
-setting[type="directory"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-path");
-}
-
-setting[type="radio"],
-setting[type="menulist"] {
-  -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-multi");
-}
-
 radio {
   -moz-binding: url("chrome://global/content/bindings/radio.xml#radio");
 }
 
 checkbox {
   -moz-binding: url("chrome://browser/content/bindings/checkbox.xml#checkbox-radio");
 }
 
 menulist {
   -moz-binding: url("chrome://browser/content/bindings.xml#menulist");
 }
 
-.chrome-select-option {
-  -moz-binding: url("chrome://browser/content/bindings.xml#chrome-select-option");
-}
-
 /* richlist defaults ------------------------------------------------------- */
 richlistbox[batch] {
   -moz-binding: url("chrome://browser/content/bindings.xml#richlistbox-batch");
 }
 
 richlistitem {
   -moz-binding: url("chrome://browser/content/bindings.xml#richlistitem");
 }
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -11,16 +11,17 @@ chrome.jar:
   content/aboutHome.xhtml              (content/aboutHome.xhtml)
 * content/aboutRights.xhtml            (content/aboutRights.xhtml)
   content/blockedSite.xhtml            (content/blockedSite.xhtml)
   content/languages.properties         (content/languages.properties)
 * content/browser.xul                  (content/browser.xul)
 * content/browser.js                   (content/browser.js)
 * content/bindings.xml                 (content/bindings.xml)
   content/bindings/checkbox.xml        (content/bindings/checkbox.xml)
+  content/bindings/settings.xml        (content/bindings/settings.xml)
   content/bindings/dialog.xml          (content/bindings/dialog.xml)
   content/browser.css                  (content/browser.css)
   content/cursor.css                   (content/cursor.css)
 % content branding %content/branding/
   content/sanitize.js                  (content/sanitize.js)
   content/exceptions.js                (content/exceptions.js)
 * content/downloads.js                 (content/downloads.js)
   content/netError.xhtml               (content/netError.xhtml)
deleted file mode 100644
--- a/mobile/android/chrome/tests/Makefile.in
+++ /dev/null
@@ -1,142 +0,0 @@
-# ***** 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.
-#
-# The Initial Developer of the Original Code is
-# the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2008
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Mark Finkle <mfinkle@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 *****
-
-DEPTH     = ../../../..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-relativesrcdir  = mobile/chrome/tests
-TESTXPI  = $(CURDIR)/$(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/addons
-ADDONSRC = $(srcdir)/addons
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_BROWSER_FILES = \
-  head.js \
-  remote_autocomplete.js \
-  remote_contentpopup.js \
-  remote_head.js \
-  remote_focus.js \
-  remote_forms.js \
-  remote_formsZoom.js \
-  remote_vkb.js \
-  browser_addons.js \
-  browser_addons_locales.js \
-  browser_appmenu.js \
-  browser_autocompletesearch.js \
-  $(info browser_awesomescreen.js is disabled because the localepicker is disabled (bug 693524)) \
-  browser_blank_01.html \
-  browser_blank_02.html \
-  browser_blank_03.html \
-  browser_bookmarks.js \
-  browser_contacts.js \
-  browser_dragger.js \
-  browser_escape.js \
-  browser_find.js \
-  browser_focus.html \
-  browser_focus.js \
-  browser_forms.html \
-  $(warning browser_forms.js disabled due to failures) \
-  browser_formsZoom.html \
-  $(warning browser_formsZoom.js disabled due to failures) \
-  $(info browser_history.js is disabled because it is random orange on XUL fennec (bug 700537)) \
-  $(info browser_localepicker.js is disabled because the localepicker is disabled (bug 694047)) \
-  browser_localepicker_escape.js \
-  browser_mainui.js \
-  browser_preferences_text.js \
-  browser_preferences_fulltoggle.js \
-  browser_rect.js \
-  $(info browser_rememberPassword.js is disabled because it is random orange on XUL fennec (bug 698387)) \
-  browser_scroll.js \
-  browser_scroll.html \
-  browser_scrollbar.js \
-  browser_select.html \
-  browser_select.js \
-  browser_sessionstore.js \
-  $(info browser_tabs.js is disabled because it is random orange on XUL fennec (bug 700537)) \
-  $(info browser_tapping.js is disabled because it is random orange on XUL fennec (bug 698387)) \
-  $(info browser_tap_content.html is disabled because it is random orange on XUL fennec (bug 698387)) \
-  browser_tapping_edit.js \
-  browser_tap_contentedit.html \
-  browser_test.js \
-  browser_vkb.js \
-  $(warning browser_viewport.js disabled due to failures) \
-  browser_viewport.sjs \
-  browser_scrollbar.sjs \
-  browser_title.sjs \
-  $(info browser_thumbnails.js is disabled because it is random orange on XUL fennec (bug 700537)) \
-  browser_install.xml \
-  browser_upgrade.rdf\
-  browser_localerepository.js \
-  browser_localerepository_pref.js \
-  browser_localerepository_buildid.js \
-  locales_list.sjs \
-  mock_autocomplete.json\
-  $(NULL)
-
-ifneq ($(OS_TARGET),Android)
-_BROWSER_FILES += \
-  browser_autocomplete.html \
-  browser_autocomplete.js \
-  browser_bookmarks_star.js \
-  browser_bookmarks_tags.js \
-  browser_click_content.html \
-  browser_click_content.js \
-  browser_contentpopup.html \
-  browser_contentpopup.js \
-  browser_navigation.js \
-  $(NULL)
-ifndef MOZ_PLATFORM_MAEMO
-_BROWSER_FILES +=  browser_sidebars.js
-endif
-endif
-
-libs:: $(_BROWSER_FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
-
-libs::
-	rm -rf $(TESTXPI)
-	$(NSINSTALL) -D $(TESTXPI)
-	if [ -d $(ADDONSRC) ]; then \
-		$(EXIT_ON_ERROR) \
-		for dir in $(ADDONSRC)/*; do \
-			base=`basename $$dir` ; \
-			(cd $$dir && zip $(TESTXPI)/$$base.xpi *) \
-		done \
-	fi
-
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-function install(data, reason) {}
-function startup(data, reason) {}
-function shutdown(data, reason) {}
-function uninstall(data, reason) {}
-
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_install1_1/install.rdf
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>addon1@tests.mozilla.org</em:id>
-    <em:version>1.0</em:version>
-    <em:updateURL>http://example.com/browser/mobile/chrome/tests/browser_upgrade.rdf</em:updateURL>
-    <em:bootstrap>true</em:bootstrap>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>toolkit@mozilla.org</em:id>
-        <em:minVersion>0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Install Tests</em:name>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_install1_2/install.rdf
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>addon2@tests.mozilla.org</em:id>
-    <em:version>2.0</em:version>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>toolkit@mozilla.org</em:id>
-        <em:minVersion>0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Install Tests 2</em:name>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_install1_3/install.rdf
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>addon1@tests.mozilla.org</em:id>
-    <em:version>3.0</em:version>
-    <em:updateURL>http://example.com/browser/mobile/chrome/tests/browser_upgrade.rdf</em:updateURL>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>toolkit@mozilla.org</em:id>
-        <em:minVersion>0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Install Tests</em:name>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_locale1/boostrap.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-function install(data, reason) {}
-function startup(data, reason) {}
-function shutdown(data, reason) {}
-function uninstall(data, reason) {}
-
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-locale mozapps te-st chrome # locale
-locale browser te-st chrome # duplicate locale
-locale browser te-st-a chrome # second locale
-locale branding te-st-3 chrome # wrong component
deleted file mode 100644
--- a/mobile/android/chrome/tests/addons/browser_locale1/install.rdf
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>locale1@tests.mozilla.org</em:id>
-    <em:version>1.0</em:version>
-    <em:type>8</em:type>
-    <em:bootstrap>true</em:bootstrap>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>toolkit@mozilla.org</em:id>
-        <em:minVersion>0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Test Locale</em:name>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/mobile/android/chrome/tests/browser_addons.js
+++ /dev/null
@@ -1,503 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-Components.utils.import("resource://gre/modules/AddonManager.jsm");
-Components.utils.import("resource://gre/modules/AddonUpdateChecker.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/NetUtil.jsm");
-
-const RELATIVE_DIR = "browser/mobile/chrome/tests/";
-const TESTROOT     = "http://example.com/" + RELATIVE_DIR;
-const TESTROOT2    = "http://example.org/" + RELATIVE_DIR;
-const PREF_LOGGING_ENABLED            = "extensions.logging.enabled";
-const PREF_SEARCH_MAXRESULTS          = "extensions.getAddons.maxResults";
-const CHROME_NAME                     = "mochikit";
-const PREF_AUTOUPDATE_DEFAULT         = "extensions.update.autoUpdateDefault"
-const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
-const PREF_GETADDONS_GETSEARCHRESULTS    = "extensions.getAddons.search.url";
-const PREF_GETADDONS_GETRECOMMENDED      = "extensions.getAddons.recommended.url";
-const PREF_GETADDONS_BROWSERECOMMENDED   = "extensions.getAddons.recommended.browseURL";
-const PREF_GETADDONS_UPDATE              = "extensions.update.url";
-const PREF_ADDONS_LOGGING                = "extensions.logging.enabled";
-const PREF_ADDONS_SECURITY               = "extensions.checkUpdateSecurity";
-const SEARCH_URL = TESTROOT + "browser_details.xml";
-const ADDON_IMG = "chrome://browser/skin/images/alert-addons-30.png";
-
-var addons = [{
-  id: "addon1@tests.mozilla.org",
-  name : "Install Tests",
-  iconURL: "http://example.com/icon.png",
-  homepageURL: "http://example.com/",
-  version: "1.0",
-  description: "Test add-on",
-  sourceURL: TESTROOT + "addons/browser_install1_1.xpi",
-  bootstrapped: true,
-  willFail: false,
-  updateIndex: 2,
-},
-{
-  id: "addon2@tests.mozilla.org",
-  name : "Install Tests 2",
-  iconURL: "http://example.com/icon.png",
-  homepageURL: "http://example.com/",
-  version: "1.0",
-  description: "Test add-on 2",
-  sourceURL: TESTROOT + "addons/browser_install1_2.xpi",
-  bootstrapped: false,
-  willFail: false,
-},
-{
-  id: "addon1@tests.mozilla.org",
-  name : "Install Tests 3",
-  iconURL: "http://example.com/icon.png",
-  homepageURL: "http://example.com/",
-  version: "1.0",
-  description: "Test add-on 3",
-  sourceURL: TESTROOT + "addons/browser_install1_3.xpi",
-  bootstrapped: false,
-  willFail: false,
-}];
-
-
-var gPendingTests = [];
-var gTestsRun = 0;
-var gTestStart = null;
-var gDate = new Date(2010, 7, 1);
-var gApp = Strings.brand.GetStringFromName("brandShortName");
-var gCategoryUtilities;
-var gSearchCount = 0;
-var gTestURL = TESTROOT + "browser_blank_01.html";
-var gCurrentTab = null;
-
-function test() {
-  waitForExplicitFinish();
-  requestLongerTimeout(2);
-  Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED,      TESTROOT + "browser_install.xml");
-  Services.prefs.setCharPref(PREF_GETADDONS_BROWSERECOMMENDED,   TESTROOT + "browser_install.xml");
-  Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, TESTROOT + "browser_install.xml");
-  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS,    TESTROOT + "browser_install.xml");
-  Services.prefs.setCharPref(PREF_GETADDONS_UPDATE,              TESTROOT + "browser_upgrade.rdf");
-  Services.prefs.setBoolPref(PREF_ADDONS_SECURITY, false);
-  Services.prefs.setBoolPref(PREF_ADDONS_LOGGING, true);
-  run_next_test();
-}
-
-function end_test() {
-  close_manager();
-  Services.prefs.clearUserPref(PREF_GETADDONS_GETRECOMMENDED);
-  Services.prefs.clearUserPref(PREF_GETADDONS_BROWSERECOMMENDED);
-  Services.prefs.clearUserPref(PREF_GETADDONS_BROWSESEARCHRESULTS);
-  Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
-  Services.prefs.clearUserPref(PREF_GETADDONS_UPDATE);
-  Services.prefs.clearUserPref(PREF_ADDONS_SECURITY);
-  Services.prefs.clearUserPref(PREF_ADDONS_LOGGING);
-}
-
-registerCleanupFunction(end_test);
-
-function add_test(test) {
-  gPendingTests.push(test);
-}
-
-function run_next_test() {
-  if (gTestsRun > 0)
-    info("Test " + gTestsRun + " took " + (Date.now() - gTestStart) + "ms");
-
-   if (!gPendingTests.length) {
-    finish();
-    return;
-  }
-
-  gTestsRun++;
-  let test = gPendingTests.shift();
-  if (test.name)
-    info("Running test " + gTestsRun + " (" + test.name + ")");
-  else
-    info("Running test " + gTestsRun);
-
-  gTestStart = Date.now();
-  test();
-}
-
-function checkAttribute(aElt, aAttr, aVal) {
-  ok(aElt.hasAttribute(aAttr), "Element has " + aAttr + " attribute");
-  if(aVal)
-    is(aElt.getAttribute(aAttr), aVal, "Element has " + aAttr + " attribute with value " + aVal);
-}
-
-function installExtension(elt, aListener) {
-  elt.parentNode.ensureElementIsVisible(elt);
-  elt.install.addListener(aListener)
-
-  let button = document.getAnonymousElementByAttribute(elt, "class", "addon-install hide-on-install hide-on-restart");
-  ok(!!button, "Extension has install button");
-  ExtensionsView.installFromRepo(elt);
-}
-
-function isRestartShown(aShown, isUpdate, aCallback) {
-  let msg = document.getElementById("addons-messages");
-  ok(!!msg, "Have message box");
-
-  let done = function(aNotification) {
-    is(!!aNotification, aShown, "Restart exists = " + aShown);
-    if (aShown && aNotification) {
-      let showsUpdate = aNotification.label.match(/update/i) != null;
-      // this test regularly fails due to race conditions here
-      is(showsUpdate, isUpdate, "Restart shows correct message");
-    }
-    msg.removeAllNotifications(true);
-    aCallback();
-  }
-
-  let notification = msg.getNotificationWithValue("restart-app");
-  if (!notification && aShown) {
-    window.addEventListener("AlertActive", function() {
-      window.removeEventListener("AlertActive", arguments.callee, true);
-      notification = msg.getNotificationWithValue("restart-app");
-      done(notification);
-    }, true);
-  } else {
-    done(notification);
-  }
-}
-
-function checkInstallAlert(aShown, aCallback) {
-  checkAlert(null, "xpinstall", null, aShown, function(aNotifyBox, aNotification) {
-    if (aShown) {
-      let button = aNotification.childNodes[0];
-      ok(!!button, "Notification has button");
-      if (button)
-        button.click();
-    }
-    aNotifyBox.removeAllNotifications(true);
-    if (aCallback)
-      aCallback();
-  });
-}
-
-function checkDownloadNotification(aCallback) {
-  let msg = /download/i;
-  checkNotification(/Add-ons/, msg, ADDON_IMG, aCallback);
-}
-
-function checkInstallNotification(aRestart, aCallback) {
-  let msg = null;
-  if (aRestart)
-    msg = /restart/i;
-  checkNotification(/Add-ons/, msg, ADDON_IMG, aCallback);
-}
-
-function checkNotification(aTitle, aMessage, aIcon, aCallback) {
-  let doTest = function() {
-    ok(document.getElementById("alerts-container").classList.contains("showing"), "Alert shown");
-    let title = document.getElementById("alerts-title").value;
-    let msg   = document.getElementById("alerts-text").textContent;
-    let img   = document.getElementById("alerts-image").getAttribute("src");
-
-    if (aTitle)
-      ok(aTitle.test(title), "Correct title alert shown: " + title);
-    if (aMessage)
-      ok(aMessage.test(msg), "Correct message shown: " + msg);
-    if (aIcon)
-      is(img, aIcon, "Correct image shown: " + aIcon);
-
-    // make sure this is hidden before another test asks about it
-    AlertsHelper.container.classList.remove("showing");
-    AlertsHelper.container.height = 0;
-    AlertsHelper.container.hidden = true;
-    aCallback();
-  };
-
-  let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
-  if (sysInfo.get("device"))
-    aCallback();
-  else
-    waitFor(doTest, function() { return AlertsHelper.container.hidden == false; });
-}
-
-function checkAlert(aId, aName, aLabel, aShown, aCallback) {
-  let msg = null;
-  if (aId)
-    msg = document.getElementById(aId);
-  else
-    msg = window.getNotificationBox(gCurrentTab.browser);
-  ok(!!msg, "Have notification box");
-
-  let haveNotification = function(notify) {
-    is(!!notify, aShown, "Notification alert exists = " + aShown);
-    if (notify && aLabel)
-      ok(aLabel.test(notify.label), "Notification shows correct message");
-    if (aCallback)
-      aCallback(msg, notify);
-  }
-
-  let notification = msg.getNotificationWithValue(aName);
-  if (!notification && aShown) {
-    window.addEventListener("AlertActive", function() {
-      window.removeEventListener("AlertActive", arguments.callee, true);
-      notification = msg.getNotificationWithValue(aName);
-      haveNotification(notification);
-    }, true);
-  } else {
-    haveNotification(notification);
-  }
-}
-
-function checkAddonListing(aAddon, elt, aType) {
-  ok(!!elt, "Element exists for addon");
-  checkAttribute(elt, "id", "urn:mozilla:item:" + aAddon.id);
-  checkAttribute(elt, "addonID", aAddon.id);
-  checkAttribute(elt, "typeName", aType);
-  checkAttribute(elt, "name", aAddon.name);
-  checkAttribute(elt, "version", aAddon.version);
-  if (aType == "search") {
-    checkAttribute(elt, "iconURL", aAddon.iconURL);
-    checkAttribute(elt, "description", aAddon.description)
-    checkAttribute(elt, "homepageURL", aAddon.homepageURL);
-    checkAttribute(elt, "sourceURL", aAddon.sourceURL);
-    ok(elt.install, "Extension has install property");
-  }
-}
-
-function checkUpdate(aSettings) {
-  let os = Services.obs;
-  let ul = new updateListener(aSettings);
-  os.addObserver(ul, "addon-update-ended", false);
-
-  ExtensionsView.updateAll();
-}
-
-function get_addon_element(aId) {
-  return document.getElementById("urn:mozilla:item:" + aId);
-}
-
-function open_manager(aView, aCallback) {
-  BrowserUI.showPanel("addons-container");
-
-  ExtensionsView.init();
-  ExtensionsView.delayedInit();
-
-  window.addEventListener("ViewChanged", function() {
-    window.removeEventListener("ViewChanged", arguments.callee, true);
-     aCallback();
-  }, true);
-}
-
-function close_manager(aCallback) {
-  let prefsButton = document.getElementById("tool-preferences");
-  prefsButton.click();
-
-  ExtensionsView.clearSection();
-  ExtensionsView.clearSection("local");
-  ExtensionsView._list = null;
-  ExtensionsView._restartCount = 0;
-  BrowserUI.hidePanel();
-
-  if (aCallback)
-    aCallback();
-}
-
-function loadUrl(aURL, aCallback, aNewTab) {
-  if (aNewTab)
-    gCurrentTab = Browser.addTab(aURL, true);
-  else
-    Browser.loadURI(aURL);
-
-  gCurrentTab.browser.messageManager.addMessageListener("pageshow", function(aMessage) {
-    if (gCurrentTab.browser.currentURI.spec == aURL) {
-      gCurrentTab.browser.messageManager.removeMessageListener(aMessage.name, arguments.callee);
-      if (aCallback)
-        setTimeout(aCallback, 0);
-    }
-  });
-}
-
-function checkInstallPopup(aName, aCallback) {
-  testPrompt("Installing Add-on", aName, [ {label: "Install", click: true},
-                                           {label: "Cancel", click: false}],
-                                  aCallback);
-}
-
-function testPrompt(aTitle, aMessage, aButtons, aCallback) {
-  function doTest() {
-    let prompt = document.getElementById("prompt-confirm-dialog");
-    ok(!!prompt, "Prompt shown");
-
-    if (prompt) {
-      let title = document.getElementById("prompt-confirm-title");
-      let message = document.getElementById("prompt-confirm-message");
-      is(aTitle, title.textContent, "Correct title shown");
-      is(aMessage, message.textContent, "Correct message shown");
-
-      let buttons = document.querySelectorAll("#prompt-confirm-buttons-box .prompt-button");
-      let clickButton = null;
-      is(buttons.length, aButtons.length, "Prompt has correct number of buttons");
-      if (buttons.length == aButtons.length) {
-        for (let i = 0; i < buttons.length; i++) {
-          is(buttons[i].label, aButtons[i].label, "Button has correct label");
-          if (aButtons[i].click)
-            clickButton = buttons[i];
-        }
-      }
-      if (clickButton)
-        clickButton.click();
-    }
-    if (aCallback)
-      aCallback();
-  }
-
-  if (!document.getElementById("prompt-confirm-dialog")) {
-    window.addEventListener("DOMWillOpenModalDialog", function() {
-      window.removeEventListener("DOMWillOpenModalDialog", arguments.callee, true);
-      // without this timeout, this can cause the prompt service to fail
-      setTimeout(doTest, 500);
-    }, true);
-  } else {
-    doTest();
-  }
-}
-
-// Installs an addon via the urlbar.
-function installFromURLBar(aAddon) {
-  return function() {
-    AddonManager.addInstallListener({
-      onInstallEnded: function (install) {
-        AddonManager.removeInstallListener(this);
-        checkInstallNotification(!aAddon.bootstrapped, function() {
-          open_manager(true, function() {
-            isRestartShown(!aAddon.bootstrapped, false, function() {
-              let elt = get_addon_element(aAddon.id);
-              if (aAddon.bootstrapped) {
-                checkAddonListing(aAddon, elt, "local");
-                let button = document.getAnonymousElementByAttribute(elt, "anonid", "uninstall-button");
-                ok(!!button, "Extension has uninstall button");
-
-                let updateButton = document.getElementById("addons-update-all");
-                is(updateButton.disabled, false, "Update button is enabled");
-
-                ExtensionsView.uninstall(elt);
-
-                elt = get_addon_element(aAddon.id);
-                ok(!elt, "Addon element removed during uninstall");
-                Browser.closeTab(gCurrentTab);
-                close_manager(run_next_test);
-              } else {
-                ok(!elt, "Extension not in list");
-                AddonManager.getAllInstalls(function(aInstalls) {
-                  for(let i = 0; i < aInstalls.length; i++) {
-                    aInstalls[i].cancel();
-                  }
-                  Browser.closeTab(gCurrentTab);
-                  close_manager(run_next_test);
-                });
-              }
-            });
-          });
-        });
-      }
-    });
-    loadUrl(gTestURL, function() {
-      loadUrl(aAddon.sourceURL, null, false);
-      checkInstallAlert(true, function() {
-        checkDownloadNotification(function() {
-          checkInstallPopup(aAddon.name, function() { });
-        });
-      });
-    }, true);
-  };
-}
-
-// Installs an addon from the addons pref pane, and then
-// updates it if requested. Checks to make sure
-// restart notifications are shown at the right time
-function installFromAddonsPage(aAddon, aDoUpdate) {
-  return function() {
-    open_manager(null, function() {
-      let elt = get_addon_element(aAddon.id);
-      checkAddonListing(aAddon, elt);
-      installExtension(elt, new installListener({
-        addon: aAddon,
-        onComplete:  function() {
-          if (aDoUpdate) {
-            checkUpdate({
-              addon: addons[aAddon.updateIndex],
-              onComplete:  function() {
-                close_manager();
-                run_next_test();
-              }
-            });
-          } else {
-            close_manager();
-            run_next_test();
-          }
-        }
-      }));
-    });
-  }
-}
-
-add_test(installFromURLBar(addons[0]));
-add_test(installFromURLBar(addons[1]));
-add_test(installFromAddonsPage(addons[0], true));
-add_test(installFromAddonsPage(addons[1], false));
-
-function installListener(aSettings) {
-  this.onComplete = aSettings.onComplete;
-  this.addon = aSettings.addon;
-}
-
-installListener.prototype = {
-  onNewInstall : function(install) { },
-  onDownloadStarted : function(install) { },
-  onDownloadProgress : function(install) { },
-  onDownloadEnded : function(install) { },
-  onDownloadCancelled : function(install) { },
-  onDownloadFailed : function(install) {
-    if(this.addon.willFail)
-      ok(false, "Install failed");
-  },
-  onInstallStarted : function(install) { },
-  onInstallEnded : function(install, addon) {
-    let self = this;
-    isRestartShown(!this.addon.bootstrapped, false, function() {
-      if(self.onComplete)
-        self.onComplete();
-    });
-  },
-  onInstallCancelled : function(install) { },
-  onInstallFailed : function(install) {
-    if(this.willFail)
-      ok(false, "Install failed");
-  },
-  onExternalInstall : function(install, existing, needsRestart) { },
-};
-
-function updateListener(aSettings) {
-  this.onComplete = aSettings.onComplete;
-  this.addon = aSettings.addon;
-}
-
-updateListener.prototype = {
-  observe: function (aSubject, aTopic, aData) {
-    switch(aTopic) {
-      case "addon-update-ended" :
-        let json = aSubject.QueryInterface(Ci.nsISupportsString).data;
-        let update = JSON.parse(json);
-        if(update.id == this.addon.id) {
-          let os = Services.obs;
-          os.removeObserver(this, "addon-update-ended", false);
-
-          let element = get_addon_element(update.id);
-          ok(!!element, "Have element for upgrade");
-
-          let self = this;
-          isRestartShown(!this.addon.bootstrapped, true, function() {
-            if(self.onComplete)
-              self.onComplete();
-          });
-        }
-        break;
-    }
-  },
-}
deleted file mode 100644
--- a/mobile/android/chrome/tests/browser_addons_locales.js
+++ /dev/null
@@ -1,64 +0,0 @@
-var localeList = serverRoot + "locales_list.sjs";
-var PREF_LOCALE_LIST = "extensions.getLocales.get.url";
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/LocaleRepository.jsm");
-Components.utils.import("resource://gre/modules/AddonManager.jsm");
-
-function test() {
-  waitForExplicitFinish();
-  runNextTest();
-}
-
-function end_test() {
-  Services.prefs.clearUserPref(PREF_LOCALE_LIST);
-}
-
-registerCleanupFunction(end_test);
-
-gTests.push({
-  addon: null,
-  desc: "Test the values returned from _getLocalesInAddon",
-  run: function() {
-    Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList);
-    LocaleRepository.getLocales(this.listLoaded.bind(this));
-  },
-
-  listLoaded: function(aLocales) {
-    is(aLocales.length, 1, "Correct number of locales were found");
-    aLocales[0].addon.install.addListener(this);
-    aLocales[0].addon.install.install();
-  },
-
-  onInstallEnded: function(aInstall, aAddon) {
-    aInstall.removeListener(this);
-    this.addon = aAddon;
-    info("Installed " + aAddon.id);
-
-    try {
-      ExtensionsView._getLocalesInAddon(aAddon, null);
-      ok(false, "_getLocalesInAddon should have thrown with a null callback");
-    } catch(ex) {
-      ok(ex, "_getLocalesInAddon requires a callback")
-    }
-
-    try {
-      ExtensionsView._getLocalesInAddon(aAddon, "foo");
-      ok(false, "_getLocalesInAddons should have thrown without a non-function callback");
-    } catch(ex) {
-      ok(ex, "_getLocalesInAddon requires the callback be a function")
-    }
-
-    ExtensionsView._getLocalesInAddon(aAddon, this.gotLocales.bind(this));
-  },
-
-  gotLocales: function(aLocales) {
-    is(aLocales.length, 2, "Correct number of locales were found");
-    ok(aLocales.indexOf("te-st") > -1, "te-st locale found");
-    ok(aLocales.indexOf("te-st-a") > -1, "te-st-a locale found");
-
-    // locales can't be restartless yet, so we can't really test the uninstall code
-    this.addon.install.cancel();
-    runNextTest();
-  }
-});
deleted file mode 100644
--- a/mobile/android/chrome/tests/browser_appmenu.js
+++ /dev/null
@@ -1,139 +0,0 @@
-let gTests = [];
-let gCurrentTest = null;
-let Panels = [AllPagesList, HistoryList, BookmarkList];
-
-let removedForTestButtons = [];
-
-function test() {
-  waitForExplicitFinish();
-
-  // Make sure we start the test with less than a full menu
-  let menu = document.getElementById("appmenu");
-  while (menu.children.length > 5)
-    removedForTestButtons.push(menu.removeChild(menu.lastChild));
-
-  setTimeout(runNextTest, 200);
-}
-
-//------------------------------------------------------------------------------
-// Iterating tests by shifting test out one by one as runNextTest is called.
-function runNextTest() {
-  // Run the next test until all tests completed
-  if (gTests.length > 0) {
-    gCurrentTest = gTests.shift();
-    info(gCurrentTest.desc);
-    gCurrentTest.run();
-  } else {
-    // Add back any removed buttons
-    let menu = document.getElementById("appmenu");
-    removedForTestButtons.forEach(function(aButton) {
-      menu.appendChild(aButton);
-    });
-
-    // Close the awesome panel just in case
-    AwesomeScreen.activePanel = null;
-    finish();
-  }
-}
-
-gTests.push({
-// This test will keep adding buttons and checking the result until there are a
-// total of 9 buttons, then it will (one at a time) hide 3 items and check the
-// result again.
-
-  desc: "Test for showing the application menu",
-  newButtons: [],
-  hidden: 0,
-
-  run: function() {
-    addEventListener("PopupChanged", gCurrentTest.popupOpened, false)
-    CommandUpdater.doCommand("cmd_menu");
-  },
-
-  addButton: function() {
-    info("Adding a new button\n");
-    let menu = document.getElementById("appmenu");
-    let newButton = menu.children[0].cloneNode(true);
-    menu.appendChild(newButton);
-    gCurrentTest.newButtons.push(newButton);
-  },
-
-  popupOpened: function() {
-    removeEventListener("PopupChanged", gCurrentTest.popupOpened, false);
-    let menu = document.getElementById("appmenu");
-    ok(!menu.hidden, "App menu is shown");
-
-    let more = document.getElementById("appmenu-more-button");
-    if (menu.children.length > 6) {
-      ok(!!more, "More button is shown");
-      addEventListener("PopupChanged", gCurrentTest.moreShown, false);
-      more.click();
-    } else {
-      ok(!more, "More button is hidden");
-      addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
-      EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
-    }
-  },
-
-  popupClosed: function() {
-    removeEventListener("PopupChanged", gCurrentTest.popupClosed, false);
-    let menu = document.getElementById("appmenu");
-    ok(document.getElementById("appmenu").hidden, "Esc hides menus");
-    if (menu.children.length < 9) {
-      gCurrentTest.addButton();
-      gCurrentTest.run();
-    } else {
-      menu.children[gCurrentTest.hidden].hidden = true;
-      gCurrentTest.hidden++;
-      addEventListener("PopupChanged", gCurrentTest.menuitemHidden, false)
-      CommandUpdater.doCommand("cmd_menu");
-    }
-  },
-
-  moreShown: function(aEvent) {
-    // AppMenu hiding
-    if (!aEvent.detail)
-      return;
-
-    let menu = document.getElementById("appmenu");
-    ok(document.getElementById("appmenu").hidden, "Clicking more button hides menu");
-
-    removeEventListener("PopupChanged", gCurrentTest.moreShown, false);
-    let listbox = document.getElementById("appmenu-overflow-commands");
-    is(listbox.childNodes.length, (menu.childNodes.length - 5), "Menu popup only shows overflow children");
-
-    addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
-  },
-
-  menuitemHidden: function() {
-    removeEventListener("PopupChanged", gCurrentTest.menuitemHidden, false);
-    let menu = document.getElementById("appmenu");
-    ok(!document.getElementById("appmenu").hidden, "App menu is shown");
-
-    let more = document.getElementById("appmenu-more-button");
-    if (menu.children.length - gCurrentTest.hidden > 6) {
-      ok(more, "More button is shown");
-      addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
-    } else {
-      ok(!more, "More button is hidden");
-      addEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false);
-    }
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
-  },
-
-  popupClosedAgain: function() {
-    removeEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false)
-    let menu = document.getElementById("appmenu");
-    while (gCurrentTest.hidden > 0) {
-      gCurrentTest.hidden--;
-      menu.children[gCurrentTest.hidden].hidden = false;
-    }
-
-    gCurrentTest.newButtons.forEach(function(aButton) {
-      menu.removeChild(aButton);
-    });
-
-    runNextTest();
-  }
-});
deleted file mode 100644
--- a/mobile/android/chrome/tests/browser_autocomplete.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<html>
-  <body>
-    <datalist id="datalist-1">
-      <option>foo</option>
-      <option disabled="true">bar</option>
-      <option value="bar">Somewhat bar</option>
-      <option label="foobar" value="_"></option>
-    </datalist>
-    <input id="input-datalist-1" list="datalist-1"></input>
-
-    <br /><br />
-
-    <datalist id="datalist-2">
-      <option>foo</option>
-      <option>bar</option>
-      <option>foobar</option>
-      <option>foobar foo</option>
-      <option>foobar foo titi</option>
-      <option>foobar foo titi toto</option>
-      <option>foobar foo titi toto tutu</option>
-    </datalist>
-    <input id="input-datalist-2" list="datalist-2"></input>
-
-    <br /><br />
-
-    <datalist id="datalist-3">
-      <option>foo</option>
-    </datalist>
-    <input id="input-datalist-3" list="datalist-3"></input>
-
-    <br /><br />
-  </body>
-</html>
-
deleted file mode 100644
--- a/mobile/android/chrome/tests/browser_autocomplete.js
+++ /dev/null
@@ -1,184 +0,0 @@
-let testURL = chromeRoot + "browser_autocomplete.html";
-messageManager.loadFrameScript(chromeRoot + "remote_autocomplete.js", true);
-
-let newTab = null;
-
-// A queue to order the tests and a handle for each test
-var gTests = [];
-var gCurrentTest = null;
-
-function test() {
-  // This test is async
-  waitForExplicitFinish();
-
-  // Ensure the form helper is initialized
-  try {
-    FormHelperUI.enabled;
-  }
-  catch(e) {
-    FormHelperUI.init();
-  }
-
-  // Need to wait until the page is loaded
-  messageManager.addMessageListener("pageshow", function(aMessage) {
-    if (newTab && newTab.browser.currentURI.spec != "about:blank") {
-      messageManager.removeMessageListener(aMessage.name, arguments.callee);
-      BrowserUI.closeAutoComplete(true);
-      setTimeout(runNextTest, 0);
-    }
-  });
-
-  newTab = Browser.addTab(testURL, true);
-}
-
-
-//------------------------------------------------------------------------------
-// Iterating tests by shifting test out one by one as runNextTest is called.
-function runNextTest() {
-  // Run the next test until all tests completed
-  if (gTests.length > 0) {
-    gCurrentTest = gTests.shift();
-    info(gCurrentTest.desc);
-    gCurrentTest.run();
-  }
-  else {
-    // Cleanup. All tests are completed at this point
-    try {
-      // Add any cleanup code here
-
-      // Close our tab when finished
-      Browser.closeTab(newTab);
-    }
-    finally {
-      // We must finialize the tests
-      finish();
-    }
-  }
-}
-
-function waitForAutocomplete(aCallback) {
-  window.addEventListener("contentpopupshown", function(aEvent) {
-    window.removeEventListener(aEvent.type, arguments.callee, false);
-    setTimeout(function() {
-      aCallback(FormHelperUI._currentElement.list);
-    }, 0);
-  }, false);
-};
-
-let data = [
-  { label: "foo", value: "foo" },
-  { label: "Somewhat bar", value: "bar" },
-  { label: "foobar", value: "_" }
-];
-
-//------------------------------------------------------------------------------
-// Case: Click on a datalist element and show suggestions
-gTests.push({
-  desc: "Click on a datalist element and show suggestions",
-
-  run: function() {
-    waitForAutocomplete(gCurrentTest.checkData);
-    AsyncTests.waitFor("TestRemoteAutocomplete:Click",
-                        { id: "input-datalist-1" }, function(json) {});
-  },
-
-  // Check that the data returned by the autocomplete handler on the content
-  // side is correct
-  checkData: function(aOptions) {
-    for (let i = 0; i < aOptions.length; i++) {
-      let option = aOptions[i];
-      let valid = data[i];
-
-      is(option.label, valid.label, "Label should be equal (" + option.label + ", " + valid.label +")");
-      is(option.value, valid.value, "Value should be equal (" + option.value + ", " + valid.value +")");
-    }
-
-    // Wait until suggestions box has been popupated
-    waitFor(gCurrentTest.checkUI, function() {
-      let suggestionsBox = document.getElementById("form-helper-suggestions");
-      return suggestionsBox.childNodes.length;
-    });
-  },
-
-  // Check that the UI reflect the specificity of the data
-  checkUI: function() {
-    let suggestionsBox = document.getElementById("form-helper-suggestions");
-    let suggestions = suggestionsBox.childNodes;
-
-    for (let i = 0; i < suggestions.length; i++) {
-      let suggestion = suggestions[i];
-      let valid = data[i];
-      let label = suggestion.getAttribute("value");
-      let value = suggestion.getAttribute("data");
-
-      is(label, valid.label, "Label should be equal (" + label + ", " + valid.label +")");
-      is(value, valid.value, "Value should be equal (" + value + ", " + valid.value +")");
-    }
-
-    gCurrentTest.checkUIClick(0);
-  },
-
-  // Ensure that clicking on a given datalist element set the right value in
-  // the input box
-  checkUIClick: function(aIndex) {
-    let suggestionsBox = document.getElementById("form-helper-suggestions");
-
-    let suggestion = suggestionsBox.childNodes[aIndex];
-    if (!suggestion) {
-      gCurrentTest.finish();
-      return;
-    }
-
-    // Use the form helper autocompletion helper
-    FormHelperUI.doAutoComplete(suggestion);
-
-    AsyncTests.waitFor("TestRemoteAutocomplete:Check", { id: "input-datalist-1" }, function(json) {
-      is(json.result, suggestion.getAttribute("data"), "The target input value should be set to " + data);
-      gCurrentTest.checkUIClick(aIndex + 1);
-    });
-  },