Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Thu, 30 Aug 2012 19:26:53 -0700
changeset 111061 e08d1ca919eef4458de91f11975a879ae30a2685
parent 111060 6bc61754b7f0f17ddd2ed6a9c2f914197855e787 (current diff)
parent 106019 6873940886b2e69241eb3d773c4bc163d4d3c6fd (diff)
child 111062 435e2bd35477170ce31737b0042489a5f5f21f87
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone18.0a1
Merge m-c to s-c.
browser/base/content/sync/setup.js
browser/components/nsBrowserGlue.js
browser/locales/en-US/chrome/browser/preferences/sync.dtd
config/makefiles/test/check-xpidl.mk
config/makefiles/xpidl.mk
js/src/ETWProvider.man
js/src/MemoryMetrics.cpp
js/src/config/makefiles/xpidl.mk
js/src/gnuplot/gcTimer.gnu
js/src/javascript-trace.d
js/src/jit-test/tests/parallelarray/element-4.js
js/src/metrics/gc/README.txt
js/src/metrics/gc/gc-test.py
js/src/metrics/gc/tests/clock.js
js/src/metrics/gc/tests/dslots.js
js/src/metrics/gc/tests/loops.js
js/src/metrics/gc/tests/objGraph.js
js/src/metrics/jint/sunspider/3d-cube.js
js/src/metrics/jint/sunspider/3d-morph.js
js/src/metrics/jint/sunspider/3d-raytrace.js
js/src/metrics/jint/sunspider/access-binary-trees.js
js/src/metrics/jint/sunspider/access-fannkuch.js
js/src/metrics/jint/sunspider/access-nbody.js
js/src/metrics/jint/sunspider/access-nsieve.js
js/src/metrics/jint/sunspider/bitops-3bit-bits-in-byte.js
js/src/metrics/jint/sunspider/bitops-bits-in-byte.js
js/src/metrics/jint/sunspider/bitops-bitwise-and.js
js/src/metrics/jint/sunspider/bitops-nsieve-bits.js
js/src/metrics/jint/sunspider/controlflow-recursive.js
js/src/metrics/jint/sunspider/crypto-aes.js
js/src/metrics/jint/sunspider/crypto-md5.js
js/src/metrics/jint/sunspider/crypto-sha1.js
js/src/metrics/jint/sunspider/date-format-tofte.js
js/src/metrics/jint/sunspider/date-format-xparb.js
js/src/metrics/jint/sunspider/math-cordic.js
js/src/metrics/jint/sunspider/math-partial-sums.js
js/src/metrics/jint/sunspider/math-spectral-norm.js
js/src/metrics/jint/sunspider/regexp-dna.js
js/src/metrics/jint/sunspider/string-base64.js
js/src/metrics/jint/sunspider/string-fasta.js
js/src/metrics/jint/sunspider/string-tagcloud.js
js/src/metrics/jint/sunspider/string-unpack-code.js
js/src/metrics/jint/sunspider/string-validate-input.js
js/src/metrics/jint/treesearch.py
js/src/metrics/jint/v8/base.js
js/src/metrics/jint/v8/crypto.js
js/src/metrics/jint/v8/deltablue.js
js/src/metrics/jint/v8/earley-boyer.js
js/src/metrics/jint/v8/raytrace.js
js/src/metrics/jint/v8/richards.js
js/src/metrics/jint/v8/run-earley-boyer.js
js/src/metrics/jint/v8/run-raytrace.js
js/src/metrics/jint/v8/run-richards.js
js/src/metrics/jint/v8/run.js
js/src/sharkctl.cpp
js/src/sharkctl.h
js/src/vprof/manifest.mk
js/src/vprof/readme.txt
js/src/vprof/testVprofMT.c
js/src/vprof/vprof.cpp
js/src/vprof/vprof.h
js/xpconnect/tests/mochitest/bug657267.jar
js/xpconnect/tests/mochitest/test_bug657267.html
netwerk/protocol/http/UserAgentOverrides.jsm
--- a/Makefile.in
+++ b/Makefile.in
@@ -64,17 +64,17 @@ endif
 ifdef COMPILE_ENVIRONMENT
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 endif
 
 
 include $(topsrcdir)/config/config.mk
 
 GARBAGE_DIRS += dist _javagen _profile _tests staticlib
-DIST_GARBAGE = config.cache config.log config.status config-defs.h \
+DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
    config/autoconf.mk \
    unallmakefiles mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 default alldep all:: $(topsrcdir)/configure config.status
 	$(RM) -r $(DIST)/sdk
 	$(RM) -r $(DIST)/include
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -351,17 +351,17 @@ nsAccDocManager::CreateDocOrRootAccessib
   // Ignore temporary, hiding, resource documents and documents without
   // docshell.
   if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
       aDocument->IsResourceDoc() || !aDocument->IsActive())
     return nullptr;
 
   // Ignore documents without presshell and not having root frame.
   nsIPresShell* presShell = aDocument->GetShell();
-  if (!presShell || !presShell->GetRootFrame())
+  if (!presShell || !presShell->GetRootFrame() || presShell->IsDestroying())
     return nullptr;
 
   // Do not create document accessible until role content is loaded, otherwise
   // we get accessible document with wrong role.
   nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
   if (!rootElm)
     return nullptr;
 
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -10,17 +10,16 @@
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibleEvent.h"
 #include "RootAccessible.h"
 
 #include "nsCaret.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAnchorElement.h"
-#include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsISelectionPrivate.h"
 #include "nsServiceManagerUtils.h"
 
 class nsIWidget;
 
--- a/accessible/src/generic/FormControlAccessible.cpp
+++ b/accessible/src/generic/FormControlAccessible.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // NOTE: alphabetically ordered
 
 #include "FormControlAccessible.h"
 #include "Role.h"
 
 #include "nsIDOMHTMLFormElement.h"
-#include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULControlElement.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // ProgressMeterAccessible
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -10,23 +10,20 @@
 #include "nsARIAMap.h"
 #include "nsEventShell.h"
 #include "nsTextEquivUtils.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsContentList.h"
+#include "nsHTMLInputElement.h"
 #include "nsIAccessibleRelation.h"
-#include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNSEditableElement.h"
-#include "nsIDOMHTMLFormElement.h"
-#include "nsIDOMHTMLLegendElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
-#include "nsIDOMNodeList.h"
 #include "nsIEditor.h"
 #include "nsIFormControl.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsISelectionController.h"
 #include "jsapi.h"
 #include "nsIJSContextStack.h"
 #include "nsIServiceManager.h"
@@ -89,33 +86,26 @@ HTMLCheckboxAccessible::DoAction(uint8_t
 }
 
 uint64_t
 HTMLCheckboxAccessible::NativeState()
 {
   uint64_t state = LeafAccessible::NativeState();
 
   state |= states::CHECKABLE;
-  bool checkState = false;   // Radio buttons and check boxes can be checked or mixed
-
-  nsCOMPtr<nsIDOMHTMLInputElement> htmlCheckboxElement =
-    do_QueryInterface(mContent);
-           
-  if (htmlCheckboxElement) {
-    htmlCheckboxElement->GetIndeterminate(&checkState);
+  nsHTMLInputElement* input = nsHTMLInputElement::FromContent(mContent);
+  if (!input)
+    return state;
 
-    if (checkState) {
-      state |= states::MIXED;
-    } else {   // indeterminate can't be checked at the same time.
-      htmlCheckboxElement->GetChecked(&checkState);
-    
-      if (checkState)
-        state |= states::CHECKED;
-    }
-  }
+  if (input->Indeterminate())
+    return state | states::MIXED;
+
+  if (input->Checked())
+    return state | states::CHECKED;
+           
   return state;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLCheckboxAccessible: Widgets
 
 bool
 HTMLCheckboxAccessible::IsWidget() const
@@ -136,23 +126,18 @@ HTMLRadioButtonAccessible::
 
 uint64_t
 HTMLRadioButtonAccessible::NativeState()
 {
   uint64_t state = AccessibleWrap::NativeState();
 
   state |= states::CHECKABLE;
 
-  bool checked = false;   // Radio buttons and check boxes can be checked
-  nsCOMPtr<nsIDOMHTMLInputElement> htmlRadioElement =
-    do_QueryInterface(mContent);
-  if (htmlRadioElement)
-    htmlRadioElement->GetChecked(&checked);
-
-  if (checked)
+  nsHTMLInputElement* input = nsHTMLInputElement::FromContent(mContent);
+  if (input && input->Checked())
     state |= states::CHECKED;
 
   return state;
 }
 
 void
 HTMLRadioButtonAccessible::GetPositionAndSizeInternal(int32_t* aPosInSet,
                                                       int32_t* aSetSize)
@@ -378,20 +363,19 @@ HTMLTextFieldAccessible::Value(nsString&
     return;
 
   nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea(do_QueryInterface(mContent));
   if (textArea) {
     textArea->GetValue(aValue);
     return;
   }
   
-  nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(mContent));
-  if (inputElement) {
-    inputElement->GetValue(aValue);
-  }
+  nsHTMLInputElement* input = nsHTMLInputElement::FromContent(mContent);
+  if (input)
+    input->GetValue(aValue);
 }
 
 void
 HTMLTextFieldAccessible::ApplyARIAState(uint64_t* aState) const
 {
   HyperTextAccessibleWrap::ApplyARIAState(aState);
 
   aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
@@ -427,18 +411,19 @@ HTMLTextFieldAccessible::NativeState()
     state |= states::PROTECTED;
   }
 
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
     state |= states::READONLY;
   }
 
   // Is it an <input> or a <textarea> ?
-  nsCOMPtr<nsIDOMHTMLInputElement> htmlInput(do_QueryInterface(mContent));
-  state |= htmlInput ? states::SINGLE_LINE : states::MULTI_LINE;
+  nsHTMLInputElement* input = nsHTMLInputElement::FromContent(mContent);
+  state |= input && input->IsSingleLineTextControl() ?
+    states::SINGLE_LINE : states::MULTI_LINE;
 
   if (!(state & states::EDITABLE) ||
       (state & (states::PROTECTED | states::MULTI_LINE)))
     return state;
 
   // Expose autocomplete states if this input is part of autocomplete widget.
   Accessible* widget = ContainerWidget();
   if (widget && widget-IsAutoComplete()) {
@@ -458,19 +443,17 @@ HTMLTextFieldAccessible::NativeState()
     // for a page if the user asks it to be. However, the kind of autocomplete
     // we're talking here is based on what the user types, where a popup of
     // possible choices comes up.
     nsAutoString autocomplete;
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete,
                       autocomplete);
 
     if (!autocomplete.LowerCaseEqualsLiteral("off")) {
-      nsCOMPtr<nsIDOMHTMLFormElement> form;
-      htmlInput->GetForm(getter_AddRefs(form));
-      nsCOMPtr<nsIContent> formContent(do_QueryInterface(form));
+      nsIContent* formContent = input->GetFormElement();
       if (formContent) {
         formContent->GetAttr(kNameSpaceID_None,
                              nsGkAtoms::autocomplete, autocomplete);
       }
 
       if (!formContent || !autocomplete.LowerCaseEqualsLiteral("off"))
         state |= states::SUPPORTS_AUTOCOMPLETION;
     }
@@ -494,17 +477,17 @@ HTMLTextFieldAccessible::GetActionName(u
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
 HTMLTextFieldAccessible::DoAction(uint8_t aIndex)
 {
   if (aIndex == 0) {
-    nsCOMPtr<nsIDOMHTMLElement> element(do_QueryInterface(mContent));
+    nsHTMLInputElement* element = nsHTMLInputElement::FromContent(mContent);
     if (element)
       return element->Focus();
 
     return NS_ERROR_FAILURE;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
--- a/accessible/src/html/HTMLSelectAccessible.cpp
+++ b/accessible/src/html/HTMLSelectAccessible.cpp
@@ -11,25 +11,20 @@
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "nsIAccessibleEvent.h"
 #include "nsTextEquivUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsCOMPtr.h"
-#include "nsIFrame.h"
+#include "nsHTMLOptionElement.h"
 #include "nsIComboboxControlFrame.h"
-#include "nsIDocument.h"
-#include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLOptGroupElement.h"
-#include "nsIDOMHTMLSelectElement.h"
+#include "nsIFrame.h"
 #include "nsIListControlFrame.h"
-#include "nsIServiceManager.h"
-#include "nsIMutableArray.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLSelectListAccessible::
@@ -233,40 +228,34 @@ HTMLSelectOptionAccessible::NativeState(
   if (!select)
     return state;
 
   uint64_t selectState = select->State();
   if (selectState & states::INVISIBLE)
     return state;
 
   // Are we selected?
-  bool isSelected = false;
-  nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(mContent));
-  if (option) {
-    option->GetSelected(&isSelected);
-    if (isSelected)
-      state |= states::SELECTED;
-  }
+  nsHTMLOptionElement* option = nsHTMLOptionElement::FromContent(mContent);
+  bool selected = option && option->Selected();
+  if (selected)
+    state |= states::SELECTED;
 
   if (selectState & states::OFFSCREEN) {
     state |= states::OFFSCREEN;
-  }
-  else if (selectState & states::COLLAPSED) {
+  } else if (selectState & states::COLLAPSED) {
     // <select> is COLLAPSED: add OFFSCREEN, if not the currently
     // visible option
-    if (!isSelected) {
+    if (!selected) {
       state |= states::OFFSCREEN;
-    }
-    else {
+    } else {
       // Clear offscreen and invisible for currently showing option
       state &= ~(states::OFFSCREEN | states::INVISIBLE);
       state |= selectState & states::OPAQUE1;
     }
-  }
-  else {
+  } else {
     // XXX list frames are weird, don't rely on Accessible's general
     // visibility implementation unless they get reimplemented in layout
     state &= ~states::OFFSCREEN;
     // <select> is not collapsed: compare bounds to calculate OFFSCREEN
     Accessible* listAcc = Parent();
     if (listAcc) {
       int32_t optionX, optionY, optionWidth, optionHeight;
       int32_t listX, listY, listWidth, listHeight;
@@ -343,18 +332,18 @@ HTMLSelectOptionAccessible::DoAction(uin
 }
 
 NS_IMETHODIMP
 HTMLSelectOptionAccessible::SetSelected(bool aSelect)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIDOMHTMLOptionElement> optionElm(do_QueryInterface(mContent));
-  return optionElm->SetSelected(aSelect);
+  nsHTMLOptionElement* option = nsHTMLOptionElement::FromContent(mContent);
+  return option ? option->SetSelected(aSelect) : NS_ERROR_FAILURE;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectOptionAccessible: Widgets
 
 Accessible*
 HTMLSelectOptionAccessible::ContainerWidget() const
 {
--- a/accessible/src/html/HTMLSelectAccessible.h
+++ b/accessible/src/html/HTMLSelectAccessible.h
@@ -2,19 +2,16 @@
 /* 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/. */
 
 #ifndef mozilla_a11y_HTMLSelectAccessible_h__
 #define mozilla_a11y_HTMLSelectAccessible_h__
 
 #include "HTMLFormControlAccessible.h"
-#include "nsIDOMHTMLOptionsCollection.h"
-#include "nsIDOMHTMLOptionElement.h"
-#include "nsIDOMNode.h"
 
 class nsIMutableArray;
 
 namespace mozilla {
 namespace a11y {
 
 /**
   *  Selects, Listboxes and Comboboxes, are made up of a number of different
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -31,16 +31,17 @@ CPPSRCS = \
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
   -I$(srcdir)/../generic \
   -I$(srcdir)/../xpcom \
+  -I$(srcdir)/../../../content/base/src \
   -I$(srcdir)/../../../content/html/content/src \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
--- a/accessible/src/xul/XULFormControlAccessible.cpp
+++ b/accessible/src/xul/XULFormControlAccessible.cpp
@@ -12,17 +12,16 @@
 #include "nsCoreUtils.h"
 #include "DocAccessible.h"
 #include "nsIAccessibleRelation.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 #include "XULMenuAccessible.h"
 
-#include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULCheckboxElement.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULTextboxElement.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -137,20 +137,16 @@ pref("browser.search.suggest.enabled", t
 pref("browser.search.noCurrentEngine", true);
 
 // enable xul error pages
 pref("browser.xul.error_pages.enabled", true);
 
 // disable color management
 pref("gfx.color_management.mode", 0);
 
-//prefer Azure/Cairo canvas
-pref("gfx.canvas.azure.enabled", true);
-pref("gfx.canvas.azure.backends", "cairo");
-
 // don't allow JS to move and resize existing windows
 pref("dom.disable_window_move_resize", true);
 
 // prevent click image resizing for nsImageDocument
 pref("browser.enable_click_image_resizing", false);
 
 // controls which bits of private data to clear. by default we clear them all.
 pref("privacy.item.cache", true);
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/payment.js
@@ -0,0 +1,77 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* 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/. */
+
+// This JS shim contains the callbacks to fire DOMRequest events for
+// navigator.pay API within the payment processor's scope.
+
+"use strict";
+
+dump("======================= payment.js ======================= \n");
+
+let { classes: Cc, interfaces: Ci, utils: Cu }  = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
+
+XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
+                                   "@mozilla.org/uuid-generator;1",
+                                   "nsIUUIDGenerator");
+
+const kClosePaymentFlowEvent = "close-payment-flow-dialog";
+
+function paymentSuccess(aResult) {
+  closePaymentFlowDialog(function notifySuccess() {
+    cpmm.sendAsyncMessage("Payment:Success", { result: aResult });
+  });
+}
+
+function paymentFailed(aErrorMsg) {
+  closePaymentFlowDialog(function notifyError() {
+    cpmm.sendAsyncMessage("Payment:Failed", { errorMsg: aErrorMsg });
+  });
+}
+
+function closePaymentFlowDialog(aCallback) {
+  // After receiving the payment provider confirmation about the
+  // successful or failed payment flow, we notify the UI to close the
+  // payment flow dialog and return to the caller application.
+  let randomId = uuidgen.generateUUID().toString();
+  let id = kClosePaymentFlowEvent + "-" + randomId;
+
+  let browser = Services.wm.getMostRecentWindow("navigator:browser");
+  let content = browser.getContentWindow();
+  if (!content) {
+    return;
+  }
+
+  let detail = {
+    type: kClosePaymentFlowEvent,
+    id: id
+  };
+
+  // In order to avoid race conditions, we wait for the UI to notify that
+  // it has successfully closed the payment flow and has recovered the
+  // caller app, before notifying the parent process to fire the success
+  // or error event over the DOMRequest.
+  content.addEventListener("mozContentEvent",
+                           function closePaymentFlowReturn(evt) {
+    if (evt.detail.id == id && aCallback) {
+      aCallback();
+    }
+
+    content.removeEventListener("mozContentEvent",
+                                closePaymentFlowReturn);
+  });
+
+  browser.shell.sendChromeEvent(detail);
+}
+
+addEventListener("DOMContentLoaded", function(e) {
+  content.wrappedJSObject.paymentSuccess = paymentSuccess;
+  content.wrappedJSObject.paymentFailed = paymentFailed;
+});
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -98,8 +98,11 @@ SettingsListener.observe('devtools.debug
 SettingsListener.observe('devtools.debugger.force-local', true, function(value) {
   Services.prefs.setBoolPref('devtools.debugger.force-local', value);
 });
 
 SettingsListener.observe('debug.log-animations.enabled', false, function(value) {
   Services.prefs.setBoolPref('layers.offmainthreadcomposition.log-animations', value);
 });
 
+SettingsListener.observe('debug.dev-mode', false, function(value) {
+  Services.prefs.setBoolPref('dom.mozApps.dev_mode', value);
+});
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -13,17 +13,18 @@ Cu.import('resource://gre/modules/XPCOMU
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
 Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 Cu.import('resource://gre/modules/AlarmService.jsm');
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
 Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
 Cu.import('resource://gre/modules/ObjectWrapper.jsm');
-Cu.import("resource://gre/modules/accessibility/AccessFu.jsm");
+Cu.import('resource://gre/modules/accessibility/AccessFu.jsm');
+Cu.import('resource://gre/modules/Payment.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
                                    'nsIStyleSheetService');
@@ -67,17 +68,31 @@ var shell = {
   reportCrash: function shell_reportCrash() {
     let crashID;
     try {
       crashID = Cc["@mozilla.org/xre/app-info;1"]
                 .getService(Ci.nsIXULRuntime).lastRunCrashID;
     } catch(e) { }
     if (Services.prefs.getBoolPref('app.reportCrashes') &&
         crashID) {
-      this.CrashSubmit().submit(crashID)
+
+      if (!Services.io.offline) {
+        this.CrashSubmit.submit(crashID);
+        return;
+      }
+
+      Services.obs.addObserver(function observer(subject, topic, state) {
+          if (topic != "network:offline-status-changed")
+            return;
+          if (state == 'online') {
+            shell.CrashSubmit.submit(crashID);
+            Services.obs.removeObserver(observer, topic);
+          }
+        }
+        , "network:offline-status-changed", false);
     }
   },
 
   get contentBrowser() {
     delete this.contentBrowser;
     return this.contentBrowser = document.getElementById('homescreen');
   },
 
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -16,16 +16,18 @@ chrome.jar:
 * content/shell.js                      (content/shell.js)
 #ifndef ANDROID
   content/screen.js                     (content/screen.js)
   content/runapp.js                     (content/runapp.js)
 #endif
   content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
 
+  content/payment.js                    (content/payment.js)
+
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
 % override chrome://global/skin/netError.css chrome://browser/content/netError.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/content/touchcontrols.css
 
   content/netError.xhtml                (content/netError.xhtml)
   content/netError.css                  (content/netError.css)
   content/images/errorpage-larry-black.png (content/images/errorpage-larry-black.png)
   content/images/errorpage-larry-white.png (content/images/errorpage-larry-white.png)
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -38,8 +38,11 @@ contract @mozilla.org/dom/activities/ui-
 component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
 contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
 category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
 
 # ContentHandler.js
 component {d18d0216-d50c-11e1-ba54-efb18d0ef0ac} ContentHandler.js
 contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216-d50c-11e1-ba54-efb18d0ef0ac}
 
+# PaymentGlue.js
+component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
+contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}
--- a/b2g/components/Makefile.in
+++ b/b2g/components/Makefile.in
@@ -21,15 +21,16 @@ EXTRA_PP_COMPONENTS = \
         AlertsService.js \
         B2GComponents.manifest \
         CameraContent.js \
         ContentHandler.js \
         ContentPermissionPrompt.js \
         DirectoryProvider.js \
         MozKeyboard.js \
         ProcessGlobal.js \
+        PaymentGlue.js \
         $(NULL)
 
 ifdef MOZ_UPDATER
 EXTRA_PP_COMPONENTS += UpdatePrompt.js
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -8,20 +8,16 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const kFormsFrameScript = "chrome://browser/content/forms.js";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
-const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
-                         .getService(Ci.nsIMessageBroadcaster);
-
-
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
 
 function MozKeyboard() { } 
 
 MozKeyboard.prototype = {
   classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
@@ -34,60 +30,59 @@ MozKeyboard.prototype = {
     "classID": Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
     "contractID": "@mozilla.org/b2g-keyboard;1",
     "interfaces": [Ci.nsIB2GKeyboard],
     "flags": Ci.nsIClassInfo.DOM_OBJECT,
     "classDescription": "B2G Virtual Keyboard"
   }),
 
   init: function mozKeyboardInit(win) {
-    messageManager.loadFrameScript(kFormsFrameScript, true);
-    messageManager.addMessageListener("Forms:Input", this);
-
     Services.obs.addObserver(this, "inner-window-destroyed", false);
     Services.obs.addObserver(this, 'in-process-browser-frame-shown', false);
     Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
 
     this._window = win;
     this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = this._utils.currentInnerWindowID;
 
     this._focusHandler = null;
   },
 
   uninit: function mozKeyboardUninit() {
     Services.obs.removeObserver(this, "inner-window-destroyed");
-    messageManager.removeMessageListener("Forms:Input", this);
+    if (this._messageManager) {
+      this._messageManager.removeMessageListener("Forms:Input", this);
+    }
     this._window = null;
     this._utils = null;
     this._focusHandler = null;
   },
 
   sendKey: function mozKeyboardSendKey(keyCode, charCode) {
     charCode = (charCode == undefined) ? keyCode : charCode;
     ["keydown", "keypress", "keyup"].forEach((function sendKey(type) {
       this._utils.sendKeyEvent(type, keyCode, charCode, null);
     }).bind(this));
   },
 
   setSelectedOption: function mozKeyboardSetSelectedOption(index) {
-    messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
+    this._messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
       "index": index
     });
   },
 
   setValue: function mozKeyboardSetValue(value) {
-    messageManager.broadcastAsyncMessage("Forms:Input:Value", {
+    this._messageManager.broadcastAsyncMessage("Forms:Input:Value", {
       "value": value
     });
   },
 
   setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) {
-    messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
+    this._messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
       "indexes": indexes || []
     });
   },
 
   set onfocuschange(val) {
     this._focusHandler = val;
   },
 
@@ -117,16 +112,17 @@ MozKeyboard.prototype = {
         this.uninit();
       }
       break;
     }
     case 'remote-browser-frame-shown':
     case 'in-process-browser-frame-shown': {
       let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
       let mm = frameLoader.messageManager;
+      this._messageManager = mm;
       mm.addMessageListener("Forms:Input", this);
       try {
         mm.loadFrameScript(kFormsFrameScript, true);
       } catch (e) {
         dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
       }
       break;
     }
new file mode 100644
--- /dev/null
+++ b/b2g/components/PaymentGlue.js
@@ -0,0 +1,134 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+// JS shim that contains the callback functions to be triggered from the
+// payment provider's code in order to fire DOMRequest events.
+const kPaymentShimFile = "chrome://browser/content/payment.js";
+
+// Type of MozChromEvents to handle payment dialogs.
+const kOpenPaymentConfirmationEvent = "open-payment-confirmation-dialog";
+const kOpenPaymentFlowEvent = "open-payment-flow-dialog";
+
+XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
+                                   "@mozilla.org/uuid-generator;1",
+                                   "nsIUUIDGenerator");
+
+function debug (s) {
+  //dump("-*- PaymentGlue: " + s + "\n");
+};
+
+function PaymentUI() {
+}
+
+PaymentUI.prototype = {
+
+  confirmPaymentRequest: function confirmPaymentRequest(aRequests,
+                                                        aSuccessCb,
+                                                        aErrorCb) {
+    let browser = Services.wm.getMostRecentWindow("navigator:browser");
+    let content = browser.getContentWindow();
+    if (!content && aErrorCb) {
+      aErrorCb.onresult("NO_CONTENT_WINDOW");
+      return;
+    }
+
+    // The UI should listen for mozChromeEvent 'open-payment-confirmation-dialog'
+    // type in order to create and show the payment request confirmation frame
+    // embeded within a trusted dialog.
+    let id = kOpenPaymentConfirmationEvent + "-" + this.getRandomId();
+    let detail = {
+      type: kOpenPaymentConfirmationEvent,
+      id: id,
+      paymentRequests: aRequests
+    };
+
+    // Once the user confirm the payment request and makes his choice, we get
+    // back to the DOM part to get the appropriate payment flow information
+    // based on the selected payment provider.
+    content.addEventListener("mozContentEvent", function handleSelection(evt) {
+      let msg = evt.detail;
+      if (msg.id != id) {
+        debug("mozContentEvent. evt.detail.id != " + id);
+        content.removeEventListener("mozContentEvent", handleSelection);
+        return;
+      }
+
+      if (msg.userSelection && aSuccessCb) {
+        aSuccessCb.onresult(msg.userSelection);
+      } else if (msg.errorMsg && aErrorCb) {
+        aErrorCb.onresult(msg.errorMsg);
+      }
+
+      content.removeEventListener("mozContentEvent", handleSelection);
+    });
+
+    browser.shell.sendChromeEvent(detail);
+  },
+
+  showPaymentFlow: function showPaymentFlow(aPaymentFlowInfo, aErrorCb) {
+    debug("showPaymentFlow. uri " + aPaymentFlowInfo.uri);
+    // We ask the UI to browse to the selected payment flow.
+    let browser = Services.wm.getMostRecentWindow("navigator:browser");
+    let content = browser.getContentWindow();
+    if (!content && aErrorCb) {
+      aErrorCb.onresult("NO_CONTENT_WINDOW");
+      return;
+    }
+
+    let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
+    let detail = {
+      type: kOpenPaymentFlowEvent,
+      id: id,
+      uri: aPaymentFlowInfo.uri,
+      method: aPaymentFlowInfo.requestMethod,
+      jwt: aPaymentFlowInfo.jwt
+    };
+
+    // At some point the UI would send the created iframe back so the
+    // callbacks for firing DOMRequest events can be loaded on its
+    // content.
+    content.addEventListener("mozContentEvent", function loadPaymentShim(evt) {
+      if (evt.detail.id != id || !evt.detail.frame) {
+        content.removeEventListener("mozContentEvent", loadPaymentShim);
+        return;
+      }
+
+      // Try to load the payment shim file containing the payment callbacks
+      // in the content script.
+      let frame = evt.detail.frame;
+      let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner)
+                        .frameLoader;
+      let mm = frameLoader.messageManager;
+      try {
+        mm.loadFrameScript(kPaymentShimFile, true);
+      } catch (e) {
+        debug("Error loading " + kPaymentShimFile + " as a frame script: " + e);
+        if (aErrorCb) {
+          aErrorCb.onresult("ERROR_LOADING_PAYMENT_SHIM");
+        }
+      } finally {
+        content.removeEventListener("mozContentEvent", loadPaymentShim);
+      }
+    });
+
+    browser.shell.sendChromeEvent(detail);
+  },
+
+  getRandomId: function getRandomId() {
+    return uuidgen.generateUUID().toString();
+  },
+
+  classID: Components.ID("{8b83eabc-7929-47f4-8b48-4dea8d887e4b}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
+}
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);
--- a/b2g/config/tooltool-manifests/ics.manifest
+++ b/b2g/config/tooltool-manifests/ics.manifest
@@ -1,14 +1,16 @@
 [
 {
-"size": 195, 
-"digest": "209d6875524e6f81c158fe7d8c543683747cb186a53ddb729c6437273404f69468d4c91bfd74a26448ad2a726da1a9b48e6243602cbe60b5d0e0f97cdb29e2cc", 
-"algorithm": "sha512", 
+"size": 195,
+"digest":
+"7236ccc28312303e2f64b0afea767ca29c6c47c4714d727d68c294c898c75d06ba53486bf66cf4d76133fa780b1f5e330204c30a461f43f9b07a3dbfd4f653d4",
+"algorithm": "sha512",
 "filename": "setup.sh"
-}, 
+},
 {
-"size": 62014571, 
-"digest": "68327ed36d8a53615fd66a300d5c022517f2f3ea0199b9d95f80683bbf1d0a154266700c8bde235467cc707c4c37341cd3f5e9816bb2c4b66efc96f9e08c92df", 
-"algorithm": "sha512", 
-"filename": "gonk-toolchain-4.tar.bz2"
+"size": 62788533,
+"digest":
+"1471e8847c9070d2062419a7be9d8921506b2d8b728d98986059771b8d45b4dba9afe54b25ba5665e4adde847cf4d5574c016c0390741139f6dd1749cd61d263",
+"algorithm": "sha512",
+"filename": "gonk-toolchain-6.tar.bz2"
 }
-]
+]
\ No newline at end of file
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -33,9 +33,11 @@ else
 MOZ_XULRUNNER=
 MOZ_PLACES=1
 fi
 
 MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 MOZ_EXTENSION_MANAGER=1
 
 MOZ_SYS_MSG=1
+
+MOZ_PAY=1
 MOZ_TOOLKIT_SEARCH=
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -155,16 +155,17 @@
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_activities.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
 @BINPATH@/components/dom_wifi.xpt
 @BINPATH@/components/dom_system_gonk.xpt
+@BINPATH@/components/dom_icc.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
 #ifdef MOZ_B2G_BT
 @BINPATH@/components/dom_bluetooth.xpt
 #endif
 @BINPATH@/components/dom_camera.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_contacts.xpt
@@ -176,16 +177,17 @@
 @BINPATH@/components/dom_file.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
+@BINPATH@/components/dom_payment.xpt
 @BINPATH@/components/dom_json.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_mms.xpt
 #endif
 @BINPATH@/components/dom_browserelement.xpt
 @BINPATH@/components/dom_messages.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
@@ -483,16 +485,21 @@
 @BINPATH@/components/ActivityWrapper.js
 
 @BINPATH@/components/TCPSocket.js
 @BINPATH@/components/TCPSocket.manifest
 
 @BINPATH@/components/AppProtocolHandler.js
 @BINPATH@/components/AppProtocolHandler.manifest
 
+@BINPATH@/components/Payment.js
+@BINPATH@/components/PaymentFlowInfo.js
+@BINPATH@/components/PaymentRequestInfo.js
+@BINPATH@/components/Payment.manifest
+
 ; Modules
 @BINPATH@/modules/*
 
 ; Safe Browsing
 @BINPATH@/components/nsURLClassifier.manifest
 @BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
 @BINPATH@/components/nsUrlClassifierLib.js
@@ -684,12 +691,13 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 #ifdef MOZ_UPDATER
 @BINPATH@/components/UpdatePrompt.js
 #endif
 @BINPATH@/components/MozKeyboard.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/ActivitiesGlue.js
 @BINPATH@/components/ProcessGlobal.js
 @BINPATH@/components/ContentHandler.js
+@BINPATH@/components/PaymentGlue.js
 
 #ifdef XP_MACOSX
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
 #endif
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -283,17 +283,17 @@
             <menuitem id="appmenu_sanitizeHistory"
                       label="&clearRecentHistory.label;"
                       key="key_sanitize"
                       command="Tools:Sanitize"/>
             <menuseparator class="hide-if-empty-places-result"/>
 #ifdef MOZ_SERVICES_SYNC
             <menuitem id="appmenu_sync-tabs"
                       class="syncTabsMenuItem"
-                      label="&syncTabsMenu.label;"
+                      label="&syncTabsMenu2.label;"
                       oncommand="BrowserOpenSyncTabs();"
                       disabled="true"/>
 #endif
             <menuitem id="appmenu_restoreLastSession"
                       class="restoreLastSession"
                       label="&historyRestoreLastSession.label;"
                       oncommand="restoreLastSession();"
                       disabled="true"/>
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -357,17 +357,17 @@
 #ifndef XP_MACOSX
                           key="showAllHistoryKb"
 #endif
                           command="Browser:ShowAllHistory"/>
                 <menuseparator id="showAllHistorySeparator"/>
 #ifdef MOZ_SERVICES_SYNC
                 <menuitem id="sync-tabs-menuitem"
                           class="syncTabsMenuItem"
-                          label="&syncTabsMenu.label;"
+                          label="&syncTabsMenu2.label;"
                           oncommand="BrowserOpenSyncTabs();"
                           disabled="true"/>
 #endif
                 <menuitem id="historyRestoreLastSession"
                           class="restoreLastSession"
                           label="&historyRestoreLastSession.label;"
                           oncommand="restoreLastSession();"
                           disabled="true"/>
--- a/browser/base/content/sync/aboutSyncTabs.xul
+++ b/browser/base/content/sync/aboutSyncTabs.xul
@@ -13,17 +13,17 @@
   %aboutSyncTabsDTD;
 ]>
 
 <window id="tabs-display"
         onload="RemoteTabViewer.init()"
         onunload="RemoteTabViewer.uninit()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml"
-        title="&tabs.otherComputers.label;">
+        title="&tabs.otherDevices.label;">
   <script type="application/javascript;version=1.8" src="chrome://browser/content/sync/aboutSyncTabs.js"/>
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
   <html:head>
     <html:link rel="icon" href="chrome://browser/skin/sync-16.png"/>
   </html:head>
 
   <popupset id="contextmenus">
     <menupopup id="tabListContext">
@@ -51,17 +51,17 @@
     </menupopup>
   </popupset>
   <richlistbox context="tabListContext" id="tabsList" seltype="multiple"
                align="center" flex="1"
                onclick="RemoteTabViewer.handleClick(event)"
                oncontextmenu="RemoteTabViewer.adjustContextMenu(event)">
     <hbox id="headers" align="center">
       <label id="tabsListHeading"
-             value="&tabs.otherComputers.label;"/>
+             value="&tabs.otherDevices.label;"/>
       <spacer flex="1"/>
       <textbox type="search"
                emptytext="&tabs.searchText.label;"
                oncommand="RemoteTabViewer.filterTabs(event)"/>
     </hbox>
 
   </richlistbox>
 </window>
--- a/browser/base/content/sync/key.xhtml
+++ b/browser/base/content/sync/key.xhtml
@@ -27,26 +27,26 @@
   </style>
 </head>
 
 <body dir="&locale.dir;">
 <h1>&syncKey.page.title;</h1>
 
 <p id="synckey" dir="ltr">SYNCKEY</p>
 
-<p>&syncKey.page.description;</p>
+<p>&syncKey.page.description2;</p>
 
 <div id="column1">
   <h2>&syncKey.keepItSecret.heading;</h2>
   <p>&syncKey.keepItSecret.description;</p>
 </div>
 
 <div id="column2">
   <h2>&syncKey.keepItSafe.heading;</h2>
-  <p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4.description;</p>
+  <p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4a.description;</p>
 </div>
 
 <p>&syncKey.findOutMore1.label;<a href="https://services.mozilla.com">https://services.mozilla.com</a>&syncKey.findOutMore2.label;</p>
 
 <footer>
  &syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label;
 </footer>
 
--- a/browser/base/content/sync/setup.js
+++ b/browser/base/content/sync/setup.js
@@ -925,16 +925,33 @@ var gSyncSetup = {
         } else {
           document.getElementById("passwordCount").hidden = true;
         }
 
         if (!Weave.Service.engineManager.get("prefs").enabled) {
           document.getElementById("prefsWipe").hidden = true;
         }
 
+        if (Weave.Engines.get("addons").enabled) {
+          let ids = Weave.Engines.get("addons")._store.getAllIDs();
+          let blessedcount = 0;
+          for each (let i in ids) {
+            if (i) {
+              blessedcount++;
+            }
+          }
+          // bug 600141 does not apply, as this does not have to support existing strings
+          document.getElementById("addonCount").value =
+            PluralForm.get(blessedcount,
+                           this._stringBundle.GetStringFromName("addonsCount.label"))
+                      .replace("#1", blessedcount);
+        } else {
+          document.getElementById("addonCount").hidden = true;
+        }
+
         this._case1Setup = true;
         break;
       case 2:
         if (this._case2Setup)
           break;
         let count = 0;
         function appendNode(label) {
           let box = document.getElementById("clientList");
--- a/browser/base/content/sync/setup.xul
+++ b/browser/base/content/sync/setup.xul
@@ -358,18 +358,18 @@
     <groupbox id="syncOptions">
     <grid>
       <columns>
         <column/>
         <column flex="1" style="-moz-margin-end: 2px"/>
       </columns>
       <rows>
         <row align="center">
-          <label value="&syncComputerName.label;"
-                 accesskey="&syncComputerName.accesskey;"
+          <label value="&syncDeviceName.label;"
+                 accesskey="&syncDeviceName.accesskey;"
                  control="syncComputerName"/>
           <textbox id="syncComputerName" flex="1"
                    onchange="gSyncUtils.changeName(this)"/>
         </row>
         <row>
           <label value="&syncMy.label;" />
           <vbox>
             <checkbox label="&engine.addons.label;"
@@ -411,67 +411,68 @@
           </columns>
           <rows flex="1">
             <row align="center">
               <radio id="resetClient"
                      class="mergeChoiceButton"
                      aria-labelledby="resetClientLabel"/>
               <label id="resetClientLabel" control="resetClient">
                 <html:strong>&choice2.merge.recommended.label;</html:strong>
-                &choice2.merge.main.label;
+                &choice2a.merge.main.label;
               </label>
             </row>
             <row align="center">
               <radio id="wipeClient"
                      class="mergeChoiceButton"
                      aria-labelledby="wipeClientLabel"/>
               <label id="wipeClientLabel"
                      control="wipeClient">
-                &choice2.client.main.label;
+                &choice2a.client.main.label;
               </label>
             </row>
             <row align="center">
               <radio id="wipeRemote"
                      class="mergeChoiceButton"
                      aria-labelledby="wipeRemoteLabel"/>
               <label id="wipeRemoteLabel"
                      control="wipeRemote">
-                &choice2.server.main.label;
+                &choice2a.server.main.label;
               </label>
             </row>
           </rows>
         </grid>
       </radiogroup>
     </groupbox>
   </wizardpage>
 
   <wizardpage id="syncOptionsConfirm"
               label="&setup.optionsConfirmPage.title;"
               onpageshow="gSyncSetup.onPageShow()">
       <deck id="chosenActionDeck">
         <vbox id="chosenActionMerge" class="confirm">
           <description class="normal">
-            &confirm.merge.label;
+            &confirm.merge2.label;
           </description>
         </vbox>
         <vbox id="chosenActionWipeClient" class="confirm">
           <description class="normal">
-            &confirm.client2.label;
+            &confirm.client3.label;
           </description>
           <separator class="thin"/>
           <vbox id="dataList">
             <label class="data indent" id="bookmarkCount"/>
             <label class="data indent" id="historyCount"/>
             <label class="data indent" id="passwordCount"/>
+            <label class="data indent" id="addonCount"/>
             <label class="data indent" id="prefsWipe"
                    value="&engine.prefs.label;"/>
           </vbox>
           <separator class="thin"/>
           <description class="normal">
-            &confirm.client.moreinfo.label;
+            &confirm.client2.moreinfo.label;
           </description>
         </vbox>
         <vbox id="chosenActionWipeServer" class="confirm">
           <description class="normal">
             &confirm.server2.label;
           </description>
           <separator class="thin"/>
           <vbox id="clientList">
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3105,27 +3105,27 @@
             let width = 0;
 
             for (let i = numPinned - 1; i >= 0; i--) {
               let tab = this.childNodes[i];
               width += tab.getBoundingClientRect().width;
               tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px";
             }
 
-            this.style.MozMarginStart = width + paddingStart + "px";
+            this.style.MozPaddingStart = width + paddingStart + "px";
 
           } else {
             this.removeAttribute("positionpinnedtabs");
 
             for (let i = 0; i < numPinned; i++) {
               let tab = this.childNodes[i];
               tab.style.MozMarginStart = "";
             }
 
-            this.style.MozMarginStart = "";
+            this.style.MozPaddingStart = "";
           }
 
           this.mTabstrip.ensureElementIsVisible(this.selectedItem, false);
         ]]></body>
       </method>
 
       <method name="_animateTabMove">
         <parameter name="event"/>
@@ -3228,22 +3228,24 @@
       </method>
 
       <method name="_finishAnimateTabMove">
         <parameter name="event"/>
         <body><![CDATA[
           if (this.getAttribute("movingtab") != "true")
             return;
 
-          let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
-          if ("animDropIndex" in draggedTab._dragData) {
-            let newIndex = draggedTab._dragData.animDropIndex;
-            if (newIndex > draggedTab._tPos)
-              newIndex--;
-            this.tabbrowser.moveTabTo(draggedTab, newIndex);
+          if (event) {
+            let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
+            if ("animDropIndex" in draggedTab._dragData) {
+              let newIndex = draggedTab._dragData.animDropIndex;
+              if (newIndex > draggedTab._tPos)
+                newIndex--;
+              this.tabbrowser.moveTabTo(draggedTab, newIndex);
+            }
           }
 
           for (let tab of this.tabbrowser.visibleTabs)
             tab.style.transform = "";
 
           this.removeAttribute("movingtab");
         ]]></body>
       </method>
@@ -3558,17 +3560,17 @@
 
         // Create a canvas to which we capture the current tab.
         let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
         let browser = tab.linkedBrowser;
         canvas.mozOpaque = true;
         canvas.width = 160;
         canvas.height = 90;
         PageThumbs.captureToCanvas(browser.contentWindow, canvas);
-        dt.setDragImage(canvas, 0, 0);
+        dt.setDragImage(canvas, -16, -16);
 
         // _dragData.offsetX/Y give the coordinates that the mouse should be
         // positioned relative to the corner of the new window created upon
         // dragend such that the mouse appears to have the same position
         // relative to the corner of the dragged tab.
         function clientX(ele) ele.getBoundingClientRect().left;
         let tabOffsetX = clientX(tab) -
                          clientX(this.children[0].pinned ? this.children[0] : this);
@@ -3711,16 +3713,17 @@
           // make sure it has a docshell
           newBrowser.docShell;
 
           let numPinned = this.tabbrowser._numPinnedTabs;
           if (newIndex < numPinned || draggedTab.pinned && newIndex == numPinned)
             this.tabbrowser.pinTab(newTab);
           this.tabbrowser.moveTabTo(newTab, newIndex);
 
+          draggedTab.parentNode._finishAnimateTabMove();
           this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
 
           // We need to select the tab after we've done
           // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
           // it triggers will correctly update our URL bar.
           this.tabbrowser.selectedTab = newTab;
         } else {
           // Pass true to disallow dropping javascript: or data: urls
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -269,16 +269,17 @@ endif
                  browser_social_chatwindow.js \
                  social_panel.html \
                  social_share_image.png \
                  social_sidebar.html \
                  social_chat.html \
                  social_flyout.html \
                  social_window.html \
                  social_worker.js \
+                 browser_bug784142.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug784142.js
@@ -0,0 +1,61 @@
+const windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+
+function test()
+{
+  waitForExplicitFinish();
+
+  // Need to enable modal dialogs for this test.
+  Services.prefs.setBoolPref("prompts.tab_modal.enabled", false);
+
+  windowMediator.addListener(promptListener);
+
+  // Open a new tab and have that tab open a new window. This is done to
+  // ensure that the new window is a normal browser window.
+  var script = "window.open('data:text/html,<button id=\"button\" onclick=\"window.close(); alert(5);\">Close</button>', null, 'width=200,height=200');";
+  gBrowser.selectedTab = 
+    gBrowser.addTab("data:text/html,<body onload='setTimeout(dotest, 0)'><script>function dotest() { " + script + "}</script></body>");
+}
+
+function windowOpened(win)
+{
+  // Wait for the page in the window to load.
+  waitForFocus(clickButton, win.content);
+}
+
+function clickButton(win)
+{
+  // Set the window in the prompt listener to indicate that the alert window
+  // is now expected to open.
+  promptListener.window = win;
+
+  // Click the Close button in the window.
+  EventUtils.synthesizeMouseAtCenter(win.content.document.getElementById("button"), { }, win);
+
+  windowMediator.removeListener(promptListener);
+  gBrowser.removeTab(gBrowser.selectedTab);
+
+  is(promptListener.message, "window appeared", "modal prompt closer didn't crash");
+  Services.prefs.clearUserPref("prompts.tab_modal.enabled", false);
+  finish();
+}
+
+var promptListener = {
+  onWindowTitleChange: function () {},
+  onOpenWindow: function (win) {
+    let domWin = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    if (!promptListener.window) {
+      // The first window that is open is the one opened by the new tab.
+      waitForFocus(windowOpened, domWin);
+    }
+    else {
+      // The second window is the alert opened when clicking the Close button in the window
+      ok(promptListener.window.closed, "window has closed");
+
+      // Assign a message so that it can be checked just before the test
+      // finishes to ensure that the alert opened properly.
+      promptListener.message = "window appeared";
+      executeSoon(function () { domWin.close() });
+    }
+  },
+  onCloseWindow: function () {}
+};
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -126,18 +126,18 @@
     <groupbox class="syncGroupBox">
       <grid>
         <columns>
           <column/>
           <column flex="1"/>
         </columns>
         <rows>
           <row align="center">
-            <label value="&syncComputerName.label;"
-                   accesskey="&syncComputerName.accesskey;"
+            <label value="&syncDeviceName.label;"
+                   accesskey="&syncDeviceName.accesskey;"
                    control="syncComputerName"/>
             <textbox id="syncComputerName"
                      onchange="gSyncUtils.changeName(this)"/>
           </row>
         </rows>
       </grid>
       <hbox>
         <label class="text-link"
--- a/browser/components/preferences/sync.xul
+++ b/browser/components/preferences/sync.xul
@@ -130,18 +130,18 @@
           <groupbox class="syncGroupBox">
             <grid>
               <columns>
                 <column/>
                 <column flex="1"/>
               </columns>
               <rows>
                 <row align="center">
-                  <label value="&syncComputerName.label;"
-                         accesskey="&syncComputerName.accesskey;"
+                  <label value="&syncDeviceName.label;"
+                         accesskey="&syncDeviceName.accesskey;"
                          control="syncComputerName"/>
                   <textbox id="syncComputerName"
                            onchange="gSyncUtils.changeName(this)"/>
                 </row>
               </rows>
             </grid>
             <hbox>
               <label class="text-link"
--- a/browser/devtools/commandline/CmdJsb.jsm
+++ b/browser/devtools/commandline/CmdJsb.jsm
@@ -20,18 +20,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 gcli.addCommand({
   name: 'jsb',
   description: gcli.lookup('jsbDesc'),
   returnValue:'string',
   params: [
     {
       name: 'url',
       type: 'string',
-      description: gcli.lookup('jsbUrlDesc'),
-      manual: 'The URL of the JS to prettify'
+      description: gcli.lookup('jsbUrlDesc')
     },
     {
       name: 'indentSize',
       type: 'number',
       description: gcli.lookup('jsbIndentSizeDesc'),
       manual: gcli.lookup('jsbIndentSizeManual'),
       defaultValue: 2
     },
--- a/browser/devtools/commandline/gcli.jsm
+++ b/browser/devtools/commandline/gcli.jsm
@@ -9335,21 +9335,37 @@ Inputter.prototype.onWindowResize = func
  * element transparent so our background shines through
  */
 Inputter.prototype.getDimensions = function() {
   // Remove this when jsdom does getBoundingClientRect(). See Bug 717269
   if (!this.element.getBoundingClientRect) {
     return undefined;
   }
 
+  var fixedLoc = {};
+  var currentElement = this.element.parentNode;
+  while (currentElement && currentElement.nodeName !== '#document') {
+    var style = this.document.defaultView.getComputedStyle(currentElement, '');
+    if (style) {
+      var position = style.getPropertyValue('position');
+      if (position === 'absolute' || position === 'fixed') {
+        var bounds = currentElement.getBoundingClientRect();
+        fixedLoc.top = bounds.top;
+        fixedLoc.left = bounds.left;
+        break;
+      }
+    }
+    currentElement = currentElement.parentNode;
+  }
+
   var rect = this.element.getBoundingClientRect();
   return {
-    top: rect.top + 1,
+    top: rect.top - (fixedLoc.top || 0) + 1,
     height: rect.bottom - rect.top - 1,
-    left: rect.left + 2,
+    left: rect.left - (fixedLoc.left || 0) + 2,
     width: rect.right - rect.left
   };
 };
 
 /**
  * Handler for the input-element.onMouseUp event
  */
 Inputter.prototype.onMouseUp = function(ev) {
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
@@ -54,17 +54,17 @@ function testSimpleCall() {
 
 function testLocationChange()
 {
   gDebugger.DebuggerController.activeThread.resume(function() {
     gDebugger.DebuggerController.client.addOneTimeListener("tabNavigated", function(aEvent, aPacket) {
       ok(true, "tabNavigated event was fired.");
       info("Still attached to the tab.");
 
-      gDebugger.addEventListener("Debugger:AfterScriptsAdded", function _onEvent(aEvent) {
+      gDebugger.addEventListener("Debugger:AfterNewScript", function _onEvent(aEvent) {
         gDebugger.removeEventListener(aEvent.type, _onEvent);
 
         isnot(gDebugger.DebuggerView.Scripts.selected, null,
           "There should be a selected script.");
         isnot(gDebugger.editor.getText().length, 0,
           "The source editor should have some text displayed.");
 
         let menulist = gDebugger.DebuggerView.Scripts._scripts;
--- a/browser/devtools/debugger/test/browser_dbg_reload-same-script.js
+++ b/browser/devtools/debugger/test/browser_dbg_reload-same-script.js
@@ -90,27 +90,27 @@ function test()
     if (step === 1) {
       testCurrentScript("-01.js", step);
       expectedScript = "-01.js";
       reloadPage();
     }
     else if (step === 2) {
       testCurrentScript("-01.js", step);
       expectedScript = "-02.js";
-      gView.Scripts.selectScript(gView.Scripts.scriptLocations[1]);
+      switchScript(1);
     }
     else if (step === 3) {
       testCurrentScript("-02.js", step);
       expectedScript = "-02.js";
       reloadPage();
     }
     else if (step === 4) {
       testCurrentScript("-02.js", step);
       expectedScript = "-01.js";
-      gView.Scripts.selectScript(gView.Scripts.scriptLocations[0]);
+      switchScript(0);
     }
     else if (step === 5) {
       testCurrentScript("-01.js", step);
       expectedScript = "-01.js";
       reloadPage();
     }
     else if (step === 6) {
       testCurrentScript("-01.js", step);
@@ -120,17 +120,17 @@ function test()
     else if (step === 7) {
       testCurrentScript("-01.js", step);
       expectedScript = "-01.js";
       reloadPage();
     }
     else if (step === 8) {
       testCurrentScript("-01.js", step);
       expectedScript = "-02.js";
-      gView.Scripts.selectScript(gView.Scripts.scriptLocations[1]);
+      switchScript(1);
     }
     else if (step === 9) {
       testCurrentScript("-02.js", step);
       expectedScript = "-02.js";
       reloadPage();
     }
     else if (step === 10) {
       testCurrentScript("-02.js", step);
@@ -140,17 +140,17 @@ function test()
     else if (step === 11) {
       testCurrentScript("-02.js", step);
       expectedScript = "-02.js";
       reloadPage();
     }
     else if (step === 12) {
       testCurrentScript("-02.js", step);
       expectedScript = "-01.js";
-      gView.Scripts.selectScript(gView.Scripts.scriptLocations[0]);
+      switchScript(0);
     }
     else if (step === 13) {
       testCurrentScript("-01.js", step);
       finishTest();
     }
   }
 
   function testCurrentScript(part, step)
@@ -161,16 +161,34 @@ function test()
     isnot(gView.Scripts.preferredScriptUrl.indexOf(part), -1,
       "The preferred script url wasn't set correctly. (" + step + ")");
     isnot(gView.Scripts.selected.indexOf(part), -1,
       "The selected script isn't the correct one. (" + step + ")");
     is(gView.Scripts.selected, scriptShownUrl,
       "The shown script is not the the correct one. (" + step + ")");
   }
 
+  function switchScript(index)
+  {
+    let scriptsView = gView.Scripts;
+    let scriptLocations = scriptsView.scriptLocations;
+    info("Available scripts: " + scriptLocations);
+
+    if (scriptLocations.length === 2) {
+      // We got all the scripts, it's safe to switch.
+      scriptsView.selectScript(scriptLocations[index]);
+      return;
+    }
+
+    window.addEventListener("Debugger:AfterNewScript", function _onEvent(aEvent) {
+      window.removeEventListener(aEvent.type, _onEvent);
+      switchScript(index);
+    });
+  }
+
   function reloadPage()
   {
     gDebuggee.location.reload();
   }
 
   registerCleanupFunction(function() {
     removeTab(gTab);
     gPane = null;
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -20,16 +20,29 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 XPCOMUtils.defineLazyModuleGetter(this, "gcli",
                                   "resource:///modules/devtools/gcli.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
                                   "resource:///modules/devtools/CmdCmd.jsm");
 
 /**
+ * Due to a number of panel bugs we need a way to check if we are running on
+ * Linux. See the comments for TooltipPanel and OutputPanel for further details.
+ *
+ * When bug 780102 is fixed all isLinux checks can be removed and we can revert
+ * to using panels.
+ */
+XPCOMUtils.defineLazyGetter(this, "isLinux", function () {
+  let os = Components.classes["@mozilla.org/xre/app-info;1"]
+           .getService(Components.interfaces.nsIXULRuntime).OS;
+  return os == "Linux";
+});
+
+/**
  * A component to manage the global developer toolbar, which contains a GCLI
  * and buttons for various developer tools.
  * @param aChromeWindow The browser window to which this toolbar is attached
  * @param aToolbarElement See browser.xul:<toolbar id="developer-toolbar">
  */
 function DeveloperToolbar(aChromeWindow, aToolbarElement)
 {
   this._chromeWindow = aChromeWindow;
@@ -534,63 +547,87 @@ function DT_resetErrorsCount(aTab)
   if (tabId in this._errorsCount) {
     this._errorsCount[tabId] = 0;
     this._updateErrorsCount(tabId);
   }
 };
 
 /**
  * Panel to handle command line output.
+ *
+ * There is a tooltip bug on Windows and OSX that prevents tooltips from being
+ * positioned properly (bug 786975). There is a Gnome panel bug on Linux that
+ * causes ugly focus issues (https://bugzilla.gnome.org/show_bug.cgi?id=621848).
+ * We now use a tooltip on Linux and a panel on OSX & Windows.
+ *
+ * If a panel has no content and no height it is not shown when openPopup is
+ * called on Windows and OSX (bug 692348) ... this prevents the panel from
+ * appearing the first time it is shown. Setting the panel's height to 1px
+ * before calling openPopup works around this issue as we resize it ourselves
+ * anyway.
+ *
  * @param aChromeDoc document from which we can pull the parts we need.
  * @param aInput the input element that should get focus.
  * @param aLoadCallback called when the panel is loaded properly.
  */
 function OutputPanel(aChromeDoc, aInput, aLoadCallback)
 {
   this._input = aInput;
   this._toolbar = aChromeDoc.getElementById("developer-toolbar");
 
   this._loadCallback = aLoadCallback;
 
   /*
-  <tooltip id="gcli-output"
+  <tooltip|panel id="gcli-output"
          noautofocus="true"
          noautohide="true"
          class="gcli-panel">
     <html:iframe xmlns:html="http://www.w3.org/1999/xhtml"
                  id="gcli-output-frame"
                  src="chrome://browser/content/devtools/commandlineoutput.xhtml"
                  flex="1"/>
-  </tooltip>
+  </tooltip|panel>
   */
 
   // TODO: Switch back from tooltip to panel when metacity focus issue is fixed:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
-  this._panel = aChromeDoc.createElement("tooltip");
+  this._panel = aChromeDoc.createElement(isLinux ? "tooltip" : "panel");
 
   this._panel.id = "gcli-output";
   this._panel.classList.add("gcli-panel");
+
+  if (isLinux) {
+    this.canHide = false;
+    this._onpopuphiding = this._onpopuphiding.bind(this);
+    this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
+  } else {
+    this._panel.setAttribute("noautofocus", "true");
+    this._panel.setAttribute("noautohide", "true");
+
+    // Bug 692348: On Windows and OSX if a panel has no content and no height
+    // openPopup fails to display it. Setting the height to 1px alows the panel
+    // to be displayed before has content or a real height i.e. the first time
+    // it is displayed.
+    this._panel.setAttribute("height", "1px");
+  }
+
   this._toolbar.parentElement.insertBefore(this._panel, this._toolbar);
 
   this._frame = aChromeDoc.createElementNS(NS_XHTML, "iframe");
   this._frame.id = "gcli-output-frame";
   this._frame.setAttribute("src", "chrome://browser/content/devtools/commandlineoutput.xhtml");
   this._frame.setAttribute("flex", "1");
   this._panel.appendChild(this._frame);
 
   this.displayedOutput = undefined;
 
   this._onload = this._onload.bind(this);
   this._frame.addEventListener("load", this._onload, true);
 
   this.loaded = false;
-  this.canHide = false;
-
-  this._onpopuphiding = this._onpopuphiding.bind(this);
-  this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
 }
 
 /**
  * Wire up the element from the iframe, and inform the _loadCallback.
  */
 OutputPanel.prototype._onload = function OP_onload()
 {
   this._frame.removeEventListener("load", this._onload, true);
@@ -615,34 +652,36 @@ OutputPanel.prototype._onload = function
 
 /**
  * Prevent the popup from hiding if it is not permitted via this.canHide.
  */
 OutputPanel.prototype._onpopuphiding = function OP_onpopuphiding(aEvent)
 {
   // TODO: When we switch back from tooltip to panel we can remove this hack:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
-  if (!this.canHide) {
+  if (isLinux && !this.canHide) {
     aEvent.preventDefault();
   }
 };
 
 /**
  * Display the OutputPanel.
  */
 OutputPanel.prototype.show = function OP_show()
 {
   // This is nasty, but displaying the panel causes it to re-flow, which can
   // change the size it should be, so we need to resize the iframe after the
   // panel has displayed
   this._panel.ownerDocument.defaultView.setTimeout(function() {
     this._resize();
   }.bind(this), 0);
 
-  this.canHide = false;
+  if (isLinux) {
+    this.canHide = false;
+  }
 
   this._panel.openPopup(this._input, "before_start", 0, 0, false, false, null);
   this._resize();
 
   this._input.focus();
 };
 
 /**
@@ -693,17 +732,19 @@ OutputPanel.prototype.update = function 
   }
 };
 
 /**
  * Detach listeners from the currently displayed Output.
  */
 OutputPanel.prototype.remove = function OP_remove()
 {
-  this.canHide = true;
+  if (isLinux) {
+    this.canHide = true;
+  }
 
   if (this._panel) {
     this._panel.hidePopup();
   }
 
   if (this.displayedOutput) {
     this.displayedOutput.onChange.remove(this.update, this);
     this.displayedOutput.onClose.remove(this.remove, this);
@@ -738,70 +779,96 @@ OutputPanel.prototype.destroy = function
  * Called by GCLI to indicate that we should show or hide one either the
  * tooltip panel or the output panel.
  */
 OutputPanel.prototype._visibilityChanged = function OP_visibilityChanged(aEvent)
 {
   if (aEvent.outputVisible === true) {
     // this.show is called by _outputChanged
   } else {
-    this.canHide = true;
+    if (isLinux) {
+      this.canHide = true;
+    }
     this._panel.hidePopup();
   }
 };
 
 
 /**
  * Panel to handle tooltips.
+ *
+ * There is a tooltip bug on Windows and OSX that prevents tooltips from being
+ * positioned properly (bug 786975). There is a Gnome panel bug on Linux that
+ * causes ugly focus issues (https://bugzilla.gnome.org/show_bug.cgi?id=621848).
+ * We now use a tooltip on Linux and a panel on OSX & Windows.
+ *
+ * If a panel has no content and no height it is not shown when openPopup is
+ * called on Windows and OSX (bug 692348) ... this prevents the panel from
+ * appearing the first time it is shown. Setting the panel's height to 1px
+ * before calling openPopup works around this issue as we resize it ourselves
+ * anyway.
+ *
  * @param aChromeDoc document from which we can pull the parts we need.
  * @param aInput the input element that should get focus.
  * @param aLoadCallback called when the panel is loaded properly.
  */
 function TooltipPanel(aChromeDoc, aInput, aLoadCallback)
 {
   this._input = aInput;
   this._toolbar = aChromeDoc.getElementById("developer-toolbar");
   this._dimensions = { start: 0, end: 0 };
 
   this._onload = this._onload.bind(this);
   this._loadCallback = aLoadCallback;
   /*
-  <tooltip id="gcli-tooltip"
+  <tooltip|panel id="gcli-tooltip"
          type="arrow"
          noautofocus="true"
          noautohide="true"
          class="gcli-panel">
     <html:iframe xmlns:html="http://www.w3.org/1999/xhtml"
                  id="gcli-tooltip-frame"
                  src="chrome://browser/content/devtools/commandlinetooltip.xhtml"
                  flex="1"/>
-  </tooltip>
+  </tooltip|panel>
   */
 
   // TODO: Switch back from tooltip to panel when metacity focus issue is fixed:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
-  this._panel = aChromeDoc.createElement("tooltip");
+  this._panel = aChromeDoc.createElement(isLinux ? "tooltip" : "panel");
 
   this._panel.id = "gcli-tooltip";
   this._panel.classList.add("gcli-panel");
+
+  if (isLinux) {
+    this.canHide = false;
+    this._onpopuphiding = this._onpopuphiding.bind(this);
+    this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
+  } else {
+    this._panel.setAttribute("noautofocus", "true");
+    this._panel.setAttribute("noautohide", "true");
+
+    // Bug 692348: On Windows and OSX if a panel has no content and no height
+    // openPopup fails to display it. Setting the height to 1px alows the panel
+    // to be displayed before has content or a real height i.e. the first time
+    // it is displayed.
+    this._panel.setAttribute("height", "1px");
+  }
+
   this._toolbar.parentElement.insertBefore(this._panel, this._toolbar);
 
   this._frame = aChromeDoc.createElementNS(NS_XHTML, "iframe");
   this._frame.id = "gcli-tooltip-frame";
   this._frame.setAttribute("src", "chrome://browser/content/devtools/commandlinetooltip.xhtml");
   this._frame.setAttribute("flex", "1");
   this._panel.appendChild(this._frame);
 
   this._frame.addEventListener("load", this._onload, true);
 
   this.loaded = false;
-  this.canHide = false;
-
-  this._onpopuphiding = this._onpopuphiding.bind(this);
-  this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
 }
 
 /**
  * Wire up the element from the iframe, and inform the _loadCallback.
  */
 TooltipPanel.prototype._onload = function TP_onload()
 {
   this._frame.removeEventListener("load", this._onload, true);
@@ -824,17 +891,17 @@ TooltipPanel.prototype._onload = functio
 
 /**
  * Prevent the popup from hiding if it is not permitted via this.canHide.
  */
 TooltipPanel.prototype._onpopuphiding = function TP_onpopuphiding(aEvent)
 {
   // TODO: When we switch back from tooltip to panel we can remove this hack:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
-  if (!this.canHide) {
+  if (isLinux && !this.canHide) {
     aEvent.preventDefault();
   }
 };
 
 /**
  * Display the TooltipPanel.
  */
 TooltipPanel.prototype.show = function TP_show(aDimensions)
@@ -846,17 +913,19 @@ TooltipPanel.prototype.show = function T
 
   // This is nasty, but displaying the panel causes it to re-flow, which can
   // change the size it should be, so we need to resize the iframe after the
   // panel has displayed
   this._panel.ownerDocument.defaultView.setTimeout(function() {
     this._resize();
   }.bind(this), 0);
 
-  this.canHide = false;
+  if (isLinux) {
+    this.canHide = false;
+  }
 
   this._resize();
   this._panel.openPopup(this._input, "before_start", aDimensions.start * 10, 0, false, false, null);
   this._input.focus();
 };
 
 /**
  * One option is to spend lots of time taking an average width of characters
@@ -891,17 +960,19 @@ TooltipPanel.prototype._resize = functio
   this._frame.height = this.document.body.scrollHeight;
 };
 
 /**
  * Hide the TooltipPanel.
  */
 TooltipPanel.prototype.remove = function TP_remove()
 {
-  this.canHide = true;
+  if (isLinux) {
+    this.canHide = true;
+  }
   this._panel.hidePopup();
 };
 
 /**
  * Hide the TooltipPanel.
  */
 TooltipPanel.prototype.destroy = function TP_destroy()
 {
@@ -929,12 +1000,14 @@ TooltipPanel.prototype.destroy = functio
  * Called by GCLI to indicate that we should show or hide one either the
  * tooltip panel or the output panel.
  */
 TooltipPanel.prototype._visibilityChanged = function TP_visibilityChanged(aEvent)
 {
   if (aEvent.tooltipVisible === true) {
     this.show(aEvent.dimensions);
   } else {
-    this.canHide = true;
+    if (isLinux) {
+      this.canHide = true;
+    }
     this._panel.hidePopup();
   }
 };
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -557,17 +557,17 @@ CssHtmlTree.prototype = {
    */
   computedViewCopy: function si_computedViewCopy(aEvent)
   {
     let win = this.styleDocument.defaultView;
     let text = win.getSelection().toString();
 
     // Tidy up block headings by moving CSS property names and their values onto
     // the same line and inserting a colon between them.
-    text = text.replace(/(.+)\r?\n\s+/g, "$1: ");
+    text = text.replace(/\t(.+)\t\t(.+)/g, "$1: $2");
 
     // Remove any MDN link titles
     text = text.replace(CssHtmlTree.HELP_LINK_TITLE, "");
     clipboardHelper.copyString(text, this.doc);
 
     if (aEvent) {
       aEvent.preventDefault();
     }
@@ -861,39 +861,39 @@ PropertyView.prototype = {
   },
 
   buildMain: function PropertyView_buildMain()
   {
     let doc = this.tree.doc;
     this.element = doc.createElementNS(HTML_NS, "tr");
     this.element.setAttribute("class", this.propertyHeaderClassName);
 
-    this.propertyHeader = doc.createElementNS(HTML_NS, "td");
-    this.element.appendChild(this.propertyHeader);
-    this.propertyHeader.setAttribute("class", "property-header");
+    this.expanderContainer = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(this.expanderContainer);
+    this.expanderContainer.setAttribute("class", "expander-container");
 
     this.matchedExpander = doc.createElementNS(HTML_NS, "div");
     this.matchedExpander.setAttribute("class", "match expander");
     this.matchedExpander.setAttribute("tabindex", "0");
     this.matchedExpander.addEventListener("click",
       this.matchedExpanderClick.bind(this), false);
     this.matchedExpander.addEventListener("keydown", function(aEvent) {
       let keyEvent = Ci.nsIDOMKeyEvent;
       if (aEvent.keyCode == keyEvent.DOM_VK_F1) {
         this.mdnLinkClick();
       }
       if (aEvent.keyCode == keyEvent.DOM_VK_RETURN ||
         aEvent.keyCode == keyEvent.DOM_VK_SPACE) {
         this.matchedExpanderClick(aEvent);
       }
     }.bind(this), false);
-    this.propertyHeader.appendChild(this.matchedExpander);
+    this.expanderContainer.appendChild(this.matchedExpander);
 
-    this.nameNode = doc.createElementNS(HTML_NS, "div");
-    this.propertyHeader.appendChild(this.nameNode);
+    this.nameNode = doc.createElementNS(HTML_NS, "td");
+    this.element.appendChild(this.nameNode);
     this.nameNode.setAttribute("class", "property-name");
     this.nameNode.textContent = this.name;
     this.nameNode.addEventListener("click", function(aEvent) {
       this.matchedExpander.focus();
     }.bind(this), false);
 
     let helpcontainer = doc.createElementNS(HTML_NS, "td");
     this.element.appendChild(helpcontainer);
--- a/browser/devtools/styleinspector/test/browser_computedview_bug_703643_context_menu_copy.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_bug_703643_context_menu_copy.js
@@ -107,20 +107,20 @@ function checkCopySelection()
 {
   let contentDocument = stylePanel.iframe.contentDocument;
   let contentWindow = stylePanel.iframe.contentWindow;
   let props = contentDocument.querySelectorAll(".property-view");
   ok(props, "captain, we have the property-view nodes");
 
   let range = document.createRange();
   range.setStart(props[0], 0);
-  range.setEnd(props[3], 3);
+  range.setEnd(props[3], 4);
   contentWindow.getSelection().addRange(range);
 
-  info("Checking that cssHtmlTree.siBoundCopyPropertyValue() " +
+  info("Checking that cssHtmlTree.siBoundCopy() " +
        " returns the correct clipboard value");
 
   let expectedPattern = "color: rgb\\(255, 255, 0\\)[\\r\\n]+" +
                  "font-family: helvetica,sans-serif[\\r\\n]+" +
                  "font-size: 16px[\\r\\n]+" +
                  "font-variant: small-caps[\\r\\n]*";
 
   SimpleTest.waitForClipboard(function CS_boundCopyCheck() {
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js
@@ -32,22 +32,16 @@ function performTest(lastFinishedRequest
   HUDService.lastFinishedRequestCallback = null;
   executeSoon(finishTest);
 }
 
 function test()
 {
   addTab(TEST_URI);
 
-  let initialLoad = true;
-
   browser.addEventListener("load", function onLoad() {
-    if (initialLoad) {
-      openConsole(null, function() {
-        HUDService.lastFinishedRequestCallback = performTest;
-        content.location.reload();
-      });
-      initialLoad = false;
-    } else {
-      browser.removeEventListener("load", onLoad, true);
-    }
+    browser.removeEventListener("load", onLoad, true);
+    openConsole(null, function() {
+      HUDService.lastFinishedRequestCallback = performTest;
+      content.location.reload();
+    });
   }, true);
 }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fa730955054b440a9e32ce282a3361cf13f198fa
GIT binary patch
literal 491
zc$@+20Tlj;P)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzjY&j7R47wLQB5yHK@>gp@kF&{Rb5bN
zGzijG&{UKVshtpNClNu)%Ekhbw2`1J>Z6HtgGN0xKEhh;{0EDsrSU_qGw%`SWF~jc
zxpQak3{VFTy2*App+P}o)NW`Vy70=Y$@eYTjRgDq)}ID15R?~1J&mx+C#(qTX;VcI
z7?3B$uiL;R>R}-rT@%F{Q^f$#FZUOjQcfPeZ$<}E18p$$rORXa`Z6Q;=m%OKw=v~i
zDrMy^zYYg%xi!g`vmMKrqSFdWO=yItW9DoVJ*XuE>5afFEf*aJP=P8AjY%zNU{t}`
z&6S2q!}*1UI~}}%g2r}h|1FKpX|M(R^hMUF<}P<`VJOHX(}C-46~4}~;<03|R$zne
zd{Hvx6aP5;bX<T>PIK`>N>asx-f>p5`o;?TlKMQ-6LJb45R#;%<gl>UHjic=P>Ck@
z+{d0AQcWVHUUFA4oxlhWu<(*~7(R)cs(MMk>=;Zw$5hvZ{W->}h6+FUwIhgP8WFVd
hn-r{!B2=PuoIg4=n|)8MY<2(u002ovPDHLkV1hfJ)Vlxx
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -164,16 +164,17 @@
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 @BINPATH@/components/dom_system.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_telephony.xpt
 @BINPATH@/components/dom_wifi.xpt
 @BINPATH@/components/dom_system_gonk.xpt
+@BINPATH@/components/dom_icc.xpt
 #endif
 @BINPATH@/components/dom_battery.xpt
 #ifdef MOZ_B2G_BT
 @BINPATH@/components/dom_bluetooth.xpt
 #endif
 @BINPATH@/components/dom_camera.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_contacts.xpt
--- a/browser/locales/en-US/chrome/browser/aboutSyncTabs.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutSyncTabs.dtd
@@ -1,14 +1,14 @@
 <!-- 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/. -->
 
-<!-- LOCALIZATION NOTE (tabs.otherComputers.label): Keep this in sync with syncTabsMenu.label from browser.dtd -->
-<!ENTITY tabs.otherComputers.label               "Tabs From Other Computers">
+<!-- LOCALIZATION NOTE (tabs.otherDevices.label): Keep this in sync with syncTabsMenu2.label from browser.dtd -->
+<!ENTITY tabs.otherDevices.label               "Tabs From Other Devices">
 
 <!ENTITY tabs.searchText.label                   "Type here to find tabs…">
 
 <!-- LOCALIZATION NOTE (tabs.context.openTab.accesskey, tabs.context.openMultipleTabs.accesskey):
      Only one of these will show at a time (based on selection), so reusing accesskey is ok. -->
 <!ENTITY tabs.context.openTab.label                   "Open This Tab">
 <!ENTITY tabs.context.openTab.accesskey               "O">
 <!ENTITY tabs.context.openMultipleTabs.label          "Open Selected Tabs">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -616,18 +616,18 @@ just addresses the organization to follo
 
 <!ENTITY downloadMonitor2.tooltip "Click to open downloads window">
 
 <!ENTITY allTabs.filter.emptyText "Search Tabs">
 <!-- Name for the tabs toolbar as spoken by screen readers.
      The word "toolbar" is appended automatically and should not be contained below! -->
 <!ENTITY tabsToolbar.label "Browser tabs">
 
-<!-- LOCALIZATION NOTE (syncTabsMenu.label): This appears in the history menu -->
-<!ENTITY syncTabsMenu.label     "Tabs From Other Computers">
+<!-- LOCALIZATION NOTE (syncTabsMenu2.label): This appears in the history menu -->
+<!ENTITY syncTabsMenu2.label     "Tabs From Other Devices">
 
 <!ENTITY syncBrand.shortName.label    "Sync">
 
 <!ENTITY syncSetup.label              "Set Up &syncBrand.shortName.label;…">
 <!ENTITY syncSetup.accesskey          "Y">
 <!ENTITY syncSyncNowItem.label        "Sync Now">
 <!ENTITY syncSyncNowItem.accesskey    "S">
 <!ENTITY syncToolbarButton.label      "Sync">
--- a/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
@@ -345,21 +345,21 @@ dbgStepDesc=Manage stepping
 # set of commands that control stepping.
 dbgStepManual=Commands to step in, out and over lines of code
 
 # LOCALIZATION NOTE (dbgStepOverDesc) A very short string used to describe the
 # function of the dbg step over command.
 dbgStepOverDesc=Executes the current statement and then stops at the next statement. If the current statement is a function call then the debugger executes the whole function, and it stops at the next statement after the function call
 
 # LOCALIZATION NOTE (dbgStepInDesc) A very short string used to describe the
-# function of the dbg step over command.
+# function of the dbg step in command.
 dbgStepInDesc=Executes the current statement and then stops at the next statement. If the current statement is a function call, then the debugger steps into that function, otherwise it stops at the next statement
 
 # LOCALIZATION NOTE (dbgStepOutDesc) A very short string used to describe the
-# function of the dbg step over command.
+# function of the dbg step out command.
 dbgStepOutDesc=Steps out of the current function and up one level if the function is nested. If in the main body, the script is executed to the end, or to the next breakpoint. The skipped statements are executed, but not stepped through
 
 # LOCALIZATION NOTE (consolecloseDesc) A very short description of the
 # 'console close' command. This string is designed to be shown in a menu
 # alongside the command name, which is why it should be as short as possible.
 consolecloseDesc=Close the console
 
 # LOCALIZATION NOTE (consoleopenDesc) A very short description of the
@@ -604,17 +604,17 @@ pagemodRemoveElementIfEmptyOnlyDesc=Remo
 # LOCALIZATION NOTE (pagemodRemoveElementResultMatchedAndRemovedElements)
 # A string displayed as the result of the 'pagemod remove element' command.
 pagemodRemoveElementResultMatchedAndRemovedElements=Elements matched by selector: %1$S. Elements removed: %2$S.
 
 # LOCALIZATION NOTE (pagemodRemoveAttributeDesc) A very short description of the
 # 'pagemod remove attribute' command. This string is designed to be shown in
 # a menu alongside the command name, which is why it should be as short as
 # possible.
-pagemodRemoveAttributeDesc=Remove matching atributes
+pagemodRemoveAttributeDesc=Remove matching attributes
 
 # LOCALIZATION NOTE (pagemodRemoveAttributeSearchAttributesDesc) A very short
 # string to describe the 'searchAttributes' parameter to the 'pagemod remove
 # attribute' command, which is displayed in a dialog when the user is using this
 # command.
 pagemodRemoveAttributeSearchAttributesDesc=Regexp specifying attributes to remove
 
 # LOCALIZATION NOTE (pagemodRemoveAttributeSearchElementsDesc) A very short
--- a/browser/locales/en-US/chrome/browser/preferences/sync.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/sync.dtd
@@ -33,15 +33,15 @@
 <!ENTITY engine.passwords.label     "Passwords">
 <!ENTITY engine.passwords.accesskey "P">
 <!ENTITY engine.prefs.label         "Preferences">
 <!ENTITY engine.prefs.accesskey     "S">
 <!ENTITY engine.addons.label        "Add-ons">
 <!ENTITY engine.addons.accesskey    "A">
 
 <!-- Device Settings -->
-<!ENTITY syncComputerName.label       "Computer Name:">
-<!ENTITY syncComputerName.accesskey   "c">
+<!ENTITY syncDeviceName.label       "Device Name:">
+<!ENTITY syncDeviceName.accesskey   "c">
 <!ENTITY unlinkDevice.label           "Unlink This Device">
 
 <!-- Footer stuff -->
 <!ENTITY prefs.tosLink.label        "Terms of Service">
 <!ENTITY prefs.ppLink.label         "Privacy Policy">
--- a/browser/locales/en-US/chrome/browser/syncKey.dtd
+++ b/browser/locales/en-US/chrome/browser/syncKey.dtd
@@ -1,18 +1,18 @@
 <!-- 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/. -->
 
 <!ENTITY syncKey.page.title               "Your &syncBrand.fullName.label; Key">
-<!ENTITY syncKey.page.description         "This key is used to decode the data in your &syncBrand.fullName.label; account. You will need to enter the key each time you configure &syncBrand.fullName.label; on a new computer or device.">
+<!ENTITY syncKey.page.description2        "This key is used to decode the data in your &syncBrand.fullName.label; account. You will need to enter the key each time you configure &syncBrand.fullName.label; on a new device.">
 <!ENTITY syncKey.keepItSecret.heading     "Keep it secret">
 <!ENTITY syncKey.keepItSecret.description "Your &syncBrand.fullName.label; account is encrypted to protect your privacy. Without this key, it would take years for anyone to decode your personal information. You are the only person who holds this key. This means you're the only one who can access your &syncBrand.fullName.label; data.">
 <!ENTITY syncKey.keepItSafe.heading       "Keep it safe">
 <!ENTITY syncKey.keepItSafe1.description  "Do not lose this key.">
 <!ENTITY syncKey.keepItSafe2.description  " We don't keep a copy of your key (that wouldn't be keeping it secret!) so ">
 <!ENTITY syncKey.keepItSafe3.description  "we can't help you recover it">
-<!ENTITY syncKey.keepItSafe4.description  " if it's lost. You'll need to use this key any time you connect a new computer or device to &syncBrand.fullName.label;.">
+<!ENTITY syncKey.keepItSafe4a.description " if it's lost. You'll need to use this key any time you connect a new device to &syncBrand.fullName.label;.">
 <!ENTITY syncKey.findOutMore1.label       "Find out more about &syncBrand.fullName.label; and your privacy at ">
 <!ENTITY syncKey.findOutMore2.label       ".">
 <!ENTITY syncKey.footer1.label            "&syncBrand.fullName.label; Terms of Service are available at ">
 <!ENTITY syncKey.footer2.label            ". The Privacy Policy is available at ">
 <!ENTITY syncKey.footer3.label            ".">
--- a/browser/locales/en-US/chrome/browser/syncSetup.dtd
+++ b/browser/locales/en-US/chrome/browser/syncSetup.dtd
@@ -7,17 +7,17 @@
 <!-- First page of the wizard -->
 
 <!ENTITY setup.pickSetupType.description2 "Welcome! If you've never used &syncBrand.fullName.label; before, you will need to create a new account.">
 <!ENTITY button.createNewAccount.label "Create a New Account">
 <!ENTITY button.haveAccount.label      "I Have an Account">
 
 <!ENTITY setup.choicePage.title.label     "Have you used &syncBrand.fullName.label; before?">
 <!ENTITY setup.choicePage.new.label       "I've never used &syncBrand.shortName.label; before">
-<!ENTITY setup.choicePage.existing.label  "I'm already using &syncBrand.shortName.label; on another computer">
+<!ENTITY setup.choicePage.existing2.label "I'm already using &syncBrand.shortName.label; on another device">
 
 <!-- New Account AND Existing Account -->
 <!ENTITY server.label               "Server">
 <!ENTITY serverType.default.label      "Default: Mozilla &syncBrand.fullName.label; server">
 <!ENTITY serverType.custom2.label   "Use a custom server…">
 <!ENTITY signIn.account2.label      "Account">
 <!ENTITY signIn.account2.accesskey  "A">
 <!ENTITY signIn.password.label      "Password">
@@ -73,41 +73,41 @@
 <!ENTITY setup.signInPage.title.label "Sign In">
 <!ENTITY existingRecoveryKey.description "You can get a copy of your Recovery Key by going to &syncBrand.shortName.label; Options on your other device, and selecting  &#x0022;My Recovery Key&#x0022; under &#x0022;Manage Account&#x0022;.">
 <!ENTITY verifying.label              "Verifying…">
 <!ENTITY resetPassword.label          "Reset Password">
 <!ENTITY resetSyncKey.label           "I have lost my other device.">
 
 <!-- Sync Options -->
 <!ENTITY setup.optionsPage.title      "Sync Options">
-<!ENTITY syncComputerName.label       "Computer Name:">
-<!ENTITY syncComputerName.accesskey   "c">
+<!ENTITY syncDeviceName.label       "Device Name:">
+<!ENTITY syncDeviceName.accesskey   "c">
 
 <!ENTITY syncMy.label               "Sync My">
 <!ENTITY engine.bookmarks.label     "Bookmarks">
 <!ENTITY engine.bookmarks.accesskey "m">
 <!ENTITY engine.tabs.label          "Tabs">
 <!ENTITY engine.tabs.accesskey      "T">
 <!ENTITY engine.history.label       "History">
 <!ENTITY engine.history.accesskey   "r">
 <!ENTITY engine.passwords.label     "Passwords">
 <!ENTITY engine.passwords.accesskey "P">
 <!ENTITY engine.prefs.label         "Preferences">
 <!ENTITY engine.prefs.accesskey     "S">
 <!ENTITY engine.addons.label        "Add-ons">
 <!ENTITY engine.addons.accesskey    "A">
 
-<!ENTITY choice2.merge.main.label      "Merge this computer's data with my &syncBrand.shortName.label; data">
+<!ENTITY choice2a.merge.main.label       "Merge this device's data with my &syncBrand.shortName.label; data">
 <!ENTITY choice2.merge.recommended.label "Recommended:">
-<!ENTITY choice2.client.main.label     "Replace all data on this computer with my &syncBrand.shortName.label; data">
-<!ENTITY choice2.server.main.label     "Replace all other devices with this computer's data">
+<!ENTITY choice2a.client.main.label      "Replace all data on this device with my &syncBrand.shortName.label; data">
+<!ENTITY choice2a.server.main.label      "Replace all other devices with this device's data">
 
 <!-- Confirm Merge Options -->
 <!ENTITY setup.optionsConfirmPage.title "Confirm">
-<!ENTITY confirm.merge.label    "&syncBrand.fullName.label; will now merge all this computer's browser data into your Sync account.">
-<!ENTITY confirm.client2.label         "Warning: The following &brandShortName; data on this computer will be deleted:">
-<!ENTITY confirm.client.moreinfo.label "&brandShortName; will then copy your &syncBrand.fullName.label; data to this computer.">
+<!ENTITY confirm.merge2.label    "&syncBrand.fullName.label; will now merge all this device's browser data into your Sync account.">
+<!ENTITY confirm.client3.label         "Warning: The following &brandShortName; data on this device  will be deleted:">
+<!ENTITY confirm.client2.moreinfo.label "&brandShortName; will then copy your &syncBrand.fullName.label; data to this device.">
 <!ENTITY confirm.server2.label         "Warning: The following devices will be overwritten with your local data:">
 
 <!-- New & Existing Account: Setup Complete -->
 <!ENTITY setup.successPage.title "Setup Complete">
 <!ENTITY changeOptions.label "You can change this preference by selecting Sync Options below.">
 <!ENTITY continueUsing.label "You may now continue using &brandShortName;.">
--- a/browser/locales/en-US/chrome/browser/syncSetup.properties
+++ b/browser/locales/en-US/chrome/browser/syncSetup.properties
@@ -27,21 +27,24 @@ bookmarksCount.label        = #1 bookmar
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #1 is the number of days (was %S for a short while, use #1 instead, even if both work)
 historyDaysCount.label      = #1 day of history;#1 days of history
 # LOCALIZATION NOTE (passwordsCount.label):
 # Semi-colon list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #1 is the number of passwords (was %S for a short while, use #1 instead, even if both work)
 passwordsCount.label        = #1 password;#1 passwords
+# LOCALIZATION NOTE (addonsCount.label):
+# #1 is the number of add-ons, see the link above for forms
+addonsCount.label        = #1 addon;#1 addons
 
 save.recoverykey.title = Save Recovery Key
 save.recoverykey.defaultfilename = Firefox Recovery Key.html
 
 newAccount.action.label = Firefox Sync is now set up to automatically sync all of your browser data.
 newAccount.change.label = You can choose exactly what to sync by selecting Sync Options below.
-resetClient.change.label = Firefox Sync will now merge all this computer's browser data into your Sync account.
-wipeClient.change.label = Firefox Sync will now replace all of the browser data on this computer with the data in your Sync account.
-wipeRemote.change.label = Firefox Sync will now replace all of the browser data in your Sync account with the data on this computer.
+resetClient.change2.label = Firefox Sync will now merge all this device's browser data into your Sync account.
+wipeClient.change2.label = Firefox Sync will now replace all of the browser data on this device with the data in your Sync account.
+wipeRemote.change2.label = Firefox Sync will now replace all of the browser data in your Sync account with the data on this device.
 existingAccount.change.label = You can change this preference by selecting Sync Options below.
 
 # Several other strings are used (via Weave.Status.login), but they come from
 #  /services/sync
--- a/browser/locales/en-US/searchplugins/twitter.xml
+++ b/browser/locales/en-US/searchplugins/twitter.xml
@@ -1,15 +1,15 @@
 <!-- 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/. -->
 
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Twitter</ShortName>
 <Description>Realtime Twitter Search</Description>
 <InputEncoding>UTF-8</InputEncoding>
-<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A/v7+D/7+/j/+/v5g/v7+YP7+/mD+/v5I/v7+KP///wD///8A////AP///wD///8A////AP///wD+/v4H/v7+UPbv4pHgx47B1K9Y3tWwWN7Ur1je3sKCx+rbuKj+/v5n/v7+GP///wD///8A////AP///wD+/v4Y+fbweM2ycMe2iB7/vI0f/8STIf/KlyL/zJki/8yZIv/LmCL/0ahK5/Hp1JH+/v4Y////AP///wD///8A7OTTaquHN+CujkXPs5ZTv6N6G/+2iB7/xpUh/8yZIv/MmSL/zJki/8yZIv/Kmy738OjUi////wD///8A////AMKtfY7w6+Ef////AP///wD///8A3sqbp8iWIf/MmSL/zJki/8yZIv/MmSL/y5gi/8mePO7+/v4w////AP///wD///8A////AP///wD+/v4H/v7+V9CtWN3KmCL/zJki/8yZIv/MmSL/zJki/8yZIv/JlyH/5tSqp/7+/mD+/v4/////AP///wD///8A+PXvJtGyZdXNnS/3y5gi/8qYIv/LmCL/zJki/8yZIv/MmSL/y5gi/82iPO7LqVfe0byMmf///wD///8A/v7+D/Do1JHKmy73ypci/8KSIP+/jyD/xpQh/8uYIv/MmSL/zJki/8qYIv+/jyD/rIEd/9nKqH7///8A////APPu4TzAlSz3wZEg/7mLH/+sgR3/uZdGz7mLH//JlyH/zJki/8yZIv/GlSH/to0r9eXbxD/Vx6dg////AP7+/h/p38WhtIsq9al/HP+kfyjuybaKgf///wCzjzjlwJAg/8qYIv/JlyH/u4wf/8CkYrn///8A////AP///wDj2sRMnHUa/7meYa7Vx6dg////AP///wD///8A2MmnYK6DHf++jiD/vo4g/62CHf/k2sQ/////AP///wD///8A8OvhH/f07w////8A////AP///wD///8A////AP///wC/p3Cfpnwc/66GKvPg1LZ8////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANXHp2DJtoqByLWKgf///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AADgPwAAwA8AAIAHAAB4BwAA+AMAAPAAAADgAQAA4AMAAMEDAADPhwAA/48AAP/nAAD//wAA//8AAA==</Image>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFjb3JuIHZlcnNpb24gMy4zPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqo9EsfAAACMUlEQVQ4jX2TMWtTURTHf+e+l1CTtCapLuLgoIuOolPB+AlqDekgpeDSufoFmoIfwNmtCKKmtYNUcJAGQcVBQSyFKuImOthE+9q0zXv37/ASWxvwwB3Ouefc8z/87jFJmGEAEuKImWHUmwFUPOcbBjVYT/M0h0cSkgAZdbm+LwkkO+wfPUgWAliTUCIGZE1CVYjNsL4iW25PI38NaCO7y6/kK6PBGY2XPjoANluTtvhzAUAVYrv3LsMzsgC21LrDSHGBY8MTDJdvgl4zYu/p+nGAEACvU5wenbbFVpHQ3dbMxS8Adv9HnlxmliiCeG8PnBFm8khnSeJtAJOELW1eAF5RKB4nau+APcHxCPkMsoeYy4IXwjOUD9jdfqlq+cqBAlQAPhG1L+GCHLmRKXwyRWerx8YDGCCCDMB3AGs0gvQBcyfIFy/R+Q2JT4ha6gEMeoX/cMXYSJ0azsB0vbTCVmueON4FuVSZgh7fvgkI6WyBtALAetMcDVISiX+A2Q7ZIQN8v9/frtClUIKk+0LV0bcGRv1q4pjsJTt9A3vO/i4D/1HsE2azRK0Y52YBaOAkyfU/i2onI1VLNzBu4ayL8IgukJAbzuITMFfVRGnN5puhaiQHGJdbYyQaxxhDXCZXcOnEISQxdKI1HDOaKL+x+WaouUrcF5dSiDMbBN3PiHOY/0AnChDbGBs495RqeVkgaxAcLu4POLAwrK6GgzENxHoLJajLsaqQxwqOXKbx/2zlH1DoZhoGHT3iAAAAAElFTkSuQmCC</Image>
 <SearchForm>https://twitter.com/search/</SearchForm>
 <Url type="text/html" method="GET" template="https://twitter.com/search/{searchTerms}">
   <Param name="partner" value="Firefox"/>
   <Param name="source" value="desktop-search"/>
 </Url>
 </SearchPlugin>
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -2597,16 +2597,17 @@ stack[anonid=browserStack][responsivemod
 /* Error counter */
 
 #developer-toolbar-webconsole[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
   background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
   border-radius: 1px;
+  -moz-margin-end: 2px;
 }
 
 #social-toolbar-button {
   -moz-appearance: toolbarbutton;
 }
 
 /* favicon for the service */
 #social-provider-image {
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css
+++ b/browser/themes/gnomestripe/devtools/csshtmltree.css
@@ -3,22 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :root {
   -moz-appearance: none;
   background: -moz-Field;
   color: -moz-FieldText;
 }
 
-.property-header {
-  padding: 5px 0;
-  white-space: nowrap;
-  vertical-align: text-top;
-}
-
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
@@ -48,42 +42,45 @@
   color: -moz-dialogtext;
   padding: 0;
 }
 
 .expander {
   -moz-appearance: treetwisty;
   padding-top: 12px;
   -moz-margin-start: 5px;
-  -moz-margin-end: 5px;
   vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .match {
   visibility: hidden;
 }
 
 .expandable {
   cursor: pointer;
   visibility: visible;
 }
 
+.expander-container {
+  vertical-align: text-top;
+}
+
 .property-name {
-  font-size: 12px;
+  padding: 2px 0;
   color: -moz-FieldText;
 }
+
 .property-value {
   padding: 0;
-  font-size: 10px;
+  -moz-padding-end: 6px;
   color: grey;
-  vertical-align: text-top;
   width: 100%;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
   cursor: pointer;
 }
--- a/browser/themes/pinstripe/devtools/csshtmltree.css
+++ b/browser/themes/pinstripe/devtools/csshtmltree.css
@@ -3,22 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :root {
   -moz-appearance: none;
   background: -moz-Field;
   color: -moz-FieldText;
 }
 
-.property-header {
-  padding: 5px 0;
-  white-space: nowrap;
-  vertical-align: text-top;
-}
-
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
@@ -50,42 +44,45 @@
 }
 
 .expander {
   -moz-appearance: treetwisty;
   width: 12px;
   height: 12px;
   padding-top: 12px;
   -moz-margin-start: 5px;
-  -moz-margin-end: 5px;
   vertical-align: middle;
 }
 
 .expander[open] {
   -moz-appearance: treetwistyopen;
 }
 
 .match {
   visibility: hidden;
 }
 
 .expandable {
   cursor: pointer;
   visibility: visible;
 }
 
+.expander-container {
+  vertical-align: text-top;
+}
+
 .property-name {
-  font-size: 12px;
+  padding: 2px 0;
   color: -moz-FieldText;
 }
+
 .property-value {
   padding: 0;
-  font-size: 10px;
+  -moz-padding-end: 6px;
   color: grey;
-  vertical-align: text-top;
   width: 100%;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
   cursor: pointer;
 }
--- a/browser/themes/winstripe/devtools/csshtmltree.css
+++ b/browser/themes/winstripe/devtools/csshtmltree.css
@@ -3,22 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 :root {
   -moz-appearance: none;
   background: -moz-Field;
   color: -moz-FieldText;
 }
 
-.property-header {
-  padding: 5px 0;
-  white-space: nowrap;
-  vertical-align: text-top;
-}
-
 /* Take away these two :visited rules to get a core dumper     */
 /* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
 .link,
 .link:visited {
   color: #0091ff;
 }
 .link,
 .helplink,
@@ -66,25 +60,29 @@
   visibility: hidden;
 }
 
 .expandable {
   cursor: pointer;
   visibility: visible;
 }
 
+.expander-container {
+  vertical-align: text-top;
+}
+
 .property-name {
-  font-size: 12px;
+  padding: 2px 0;
   color: -moz-FieldText;
 }
+
 .property-value {
   padding: 0;
-  font-size: 10px;
+  -moz-padding-end: 6px;
   color: grey;
-  vertical-align: text-top;
   width: 100%;
 }
 
 .rule-link {
   text-align: end;
   -moz-padding-start: 10px;
   cursor: pointer;
 }
--- a/build/autoconf/config.status.m4
+++ b/build/autoconf/config.status.m4
@@ -8,40 +8,40 @@ define([MOZ_DIVERSION_SUBST], 11)
 dnl Replace AC_SUBST to store values in a format suitable for python.
 dnl The necessary comma after the tuple can't be put here because it
 dnl can mess around with things like:
 dnl    AC_SOMETHING(foo,AC_SUBST(),bar)
 define([AC_SUBST],
 [ifdef([AC_SUBST_$1], ,
 [define([AC_SUBST_$1], )dnl
 AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
-        (''' $1 ''', r''' [$]$1 ''')
+    (''' $1 ''', r''' [$]$1 ''')
 AC_DIVERT_POP()dnl
 ])])
 
 dnl Wrap AC_DEFINE to store values in a format suitable for python.
 dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h,
 dnl which is #included during some compile checks.
 dnl The necessary comma after the tuple can't be put here because it
 dnl can mess around with things like:
 dnl    AC_SOMETHING(foo,AC_DEFINE(),bar)
 define([_MOZ_AC_DEFINE], defn([AC_DEFINE]))
 define([AC_DEFINE],
 [cat >> confdefs.pytmp <<\EOF
-        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+    (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
 EOF
 ifelse($#, 2, _MOZ_AC_DEFINE([$1], [$2]), $#, 3, _MOZ_AC_DEFINE([$1], [$2], [$3]),_MOZ_AC_DEFINE([$1]))dnl
 ])
 
 dnl Wrap AC_DEFINE_UNQUOTED to store values in a format suitable for
 dnl python.
 define([_MOZ_AC_DEFINE_UNQUOTED], defn([AC_DEFINE_UNQUOTED]))
 define([AC_DEFINE_UNQUOTED],
 [cat >> confdefs.pytmp <<EOF
-        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+    (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
 EOF
 ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
 ])
 
 dnl Replace AC_OUTPUT to create and call a python config.status
 define([AC_OUTPUT],
 [dnl Top source directory in Windows format (as opposed to msys format).
 WIN_TOP_SRC=
@@ -75,98 +75,100 @@ changequote(<<<, >>>)dnl
 echo creating $CONFIG_STATUS
 
 extra_python_path=${COMM_BUILD:+"'mozilla', "}
 
 cat > $CONFIG_STATUS <<EOF
 #!${PYTHON}
 # coding=$encoding
 
-import os, sys
+import os
 dnl topsrcdir is the top source directory in native form, as opposed to a
 dnl form suitable for make.
 topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
 if not os.path.isabs(topsrcdir):
     topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
-dnl Don't rely on virtualenv here. Standalone js doesn't use it.
-sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
-from ConfigStatus import config_status
 
-args = {
-    'topsrcdir': topsrcdir,
-    'topobjdir': os.path.dirname(<<<__file__>>>),
+topobjdir = os.path.dirname(<<<__file__>>>)
 
 dnl All defines and substs are stored with an additional space at the beginning
 dnl and at the end of the string, to avoid any problem with values starting or
 dnl ending with quotes.
-    'defines': [(name[1:-1], value[1:-1]) for name, value in [
+defines = [(name[1:-1], value[1:-1]) for name, value in [
 EOF
 
 dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but
 dnl lacks the final comma (see above).
 sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS
 rm confdefs.pytmp confdefs.h
 
 cat >> $CONFIG_STATUS <<\EOF
-    ] ],
+] ]
 
-    'substs': [(name[1:-1], value[1:-1]) for name, value in [
+substs = [(name[1:-1], value[1:-1]) for name, value in [
 EOF
 
 dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
 dnl expected format, but lacks the final comma (see above).
 sed 's/$/,/' >> $CONFIG_STATUS <<EOF
 undivert(MOZ_DIVERSION_SUBST)dnl
 EOF
 
 cat >> $CONFIG_STATUS <<\EOF
-    ] ],
+] ]
 
 dnl List of files to apply AC_SUBSTs to. This is the list of files given
 dnl as an argument to AC_OUTPUT ($1)
-    'files': [
+files = [
 EOF
 
 for out in $1; do
-  echo "        '$out'," >> $CONFIG_STATUS
+  echo "    '$out'," >> $CONFIG_STATUS
 done
 
 cat >> $CONFIG_STATUS <<\EOF
-    ],
+]
 
 dnl List of header files to apply AC_DEFINEs to. This is stored in the
 dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER.
-    'headers': [
+headers = [
 EOF
 
 ifdef(<<<AC_LIST_HEADER>>>, <<<
 HEADERS="AC_LIST_HEADER"
 for header in $HEADERS; do
-  echo "        '$header'," >> $CONFIG_STATUS
+  echo "    '$header'," >> $CONFIG_STATUS
 done
 >>>)dnl
 
 cat >> $CONFIG_STATUS <<\EOF
-    ],
+]
 
 dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
-    'non_global_defines': [
+non_global_defines = [
 EOF
 
 if test -n "$_NON_GLOBAL_ACDEFINES"; then
   for var in $_NON_GLOBAL_ACDEFINES; do
-    echo "        '$var'," >> $CONFIG_STATUS
+    echo "    '$var'," >> $CONFIG_STATUS
   done
 fi
 
-cat >> $CONFIG_STATUS <<\EOF
-    ]
-}
+cat >> $CONFIG_STATUS <<EOF
+]
+
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers']
 
 dnl Do the actual work
-config_status(**args)
+if __name__ == '__main__':
+    args = dict([(name, globals()[name]) for name in __all__])
+    import sys
+dnl Don't rely on virtualenv here. Standalone js doesn't use it.
+    sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
+    from ConfigStatus import config_status
+    config_status(**args)
 EOF
 changequote([, ])
 chmod +x $CONFIG_STATUS
 rm -fr confdefs* $ac_clean_files
 dnl Execute config.status, unless --no-create was passed to configure.
 test "$no_create" = yes || ${PYTHON} $CONFIG_STATUS || exit 1
 ])
--- a/build/cl.py
+++ b/build/cl.py
@@ -39,17 +39,17 @@ def InvokeClWithDependencyGeneration(cmd
         else:
             sys.stdout.write(line) # Make sure we preserve the relevant output
                                    # from cl
 
     ret = cl.wait()
     if ret != 0 or target == "":
         sys.exit(ret)
 
-    depsdir = os.path.normpath(os.path.join(os.path.dirname(target), ".deps"))
+    depsdir = os.path.normpath(os.path.join(os.curdir, ".deps"))
     depstarget = os.path.join(depsdir, depstarget)
     if not os.path.isdir(depsdir):
         try:
             os.makedirs(depsdir)
         except OSError:
             pass # This suppresses the error we get when the dir exists, at the
                  # cost of masking failure to create the directory.  We'll just
                  # die on the next line though, so it's not that much of a loss.
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -496,27 +496,27 @@ class DeviceManager:
     returns:
     success: file is created in <testroot>/logcat.log
     failure:
     """
     #TODO: spawn this off in a separate thread/process so we can collect all the logcat information
 
     # Right now this is just clearing the logcat so we can only see what happens after this call.
     buf = StringIO.StringIO()
-    self.shell(['/system/bin/logcat', '-c'], buf)
+    self.shell(['/system/bin/logcat', '-c'], buf, root=True)
 
   def getLogcat(self):
     """
     external function
     returns: data from the local file
     success: file is in 'filename'
     failure: None
     """
     buf = StringIO.StringIO()
-    if self.shell(["/system/bin/logcat", "-d", "dalvikvm:S", "ConnectivityService:S", "WifiMonitor:S", "WifiStateTracker:S", "wpa_supplicant:S", "NetworkStateTracker:S"], buf) != 0:
+    if self.shell(["/system/bin/logcat", "-d", "dalvikvm:S", "ConnectivityService:S", "WifiMonitor:S", "WifiStateTracker:S", "wpa_supplicant:S", "NetworkStateTracker:S"], buf, root=True) != 0:
       return None
 
     return str(buf.getvalue()[0:-1]).rstrip().split('\r')
 
   @abstractmethod
   def chmodDir(self, remoteDir):
     """
     external function
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -91,24 +91,28 @@ class DeviceManagerADB(DeviceManager):
       self.disconnectRemoteADB()
 
   # external function: executes shell command on device.
   # timeout is specified in seconds, and if no timeout is given, 
   # we will run until the script returns
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False):
     # FIXME: this function buffers all output of the command into memory,
     # always. :(
 
     # Getting the return code is more complex than you'd think because adb
     # doesn't actually return the return code from a process, so we have to
     # capture the output to get it
-    cmdline = "%s; echo $?" % self._escapedCommandLine(cmd)
+    if root:
+      cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd)
+    else:
+      cmdline = self._escapedCommandLine(cmd)
+    cmdline += "; echo $?"
 
     # prepend cwd and env to command if necessary
     if cwd:
       cmdline = "cd %s; %s" % (cwd, cmdline)
     if env:
       envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
       cmdline = envstr + "; " + cmdline
 
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -9,16 +9,17 @@ import time
 import os
 import re
 import posixpath
 import subprocess
 from threading import Thread
 import StringIO
 from devicemanager import DeviceManager, FileError, NetworkTools, _pop_last_line
 import errno
+from distutils.version import StrictVersion
 
 class AgentError(Exception):
   "SUTAgent-specific exception."
 
   def __init__(self, msg= '', fatal = False):
     self.msg = msg
     self.fatal = fatal
 
@@ -47,17 +48,22 @@ class DeviceManagerSUT(DeviceManager):
   def __init__(self, host, port = 20701, retrylimit = 5, deviceRoot = None):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
     self.deviceRoot = deviceRoot
     if self.getDeviceRoot() == None:
-        raise BaseException("Failed to connect to SUT Agent and retrieve the device root.")
+      raise BaseException("Failed to connect to SUT Agent and retrieve the device root.")
+    try:
+      verstring = self.runCmds([{ 'cmd': 'ver' }])
+      self.agentVersion = re.sub('SUTAgentAndroid Version ', '', verstring)
+    except AgentError, err:
+      raise BaseException("Failed to get SUTAgent version")
 
   def _cmdNeedsResponse(self, cmd):
     """ Not all commands need a response from the agent:
         * rebt obviously doesn't get a response
         * uninstall performs a reboot to ensure starting in a clean state and
           so also doesn't look for a response
     """
     noResponseCmds = [re.compile('^rebt'),
@@ -258,26 +264,48 @@ class DeviceManagerSUT(DeviceManager):
       except:
         self._sock = None
         raise AgentError("Error closing socket")
 
   # external function: executes shell command on device
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False):
     cmdline = self._escapedCommandLine(cmd)
     if env:
       cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
 
+    haveExecSu = (StrictVersion(self.agentVersion) >= StrictVersion('1.13'))
+
+    # Depending on agent version we send one of the following commands here:
+    # * exec (run as normal user)
+    # * execsu (run as privileged user)
+    # * execcwd (run as normal user from specified directory)
+    # * execcwdsu (run as privileged user from specified directory)
+
+    cmd = "exec"
+    if cwd:
+      cmd += "cwd"
+    if root and haveExecSu:
+      cmd += "su"
+
     try:
       if cwd:
-        self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile, timeout)
+        self.sendCmds([{ 'cmd': '%s %s %s' % (cmd, cwd, cmdline) }], outputfile, timeout)
       else:
-        self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile, timeout)
+        if (not root) or haveExecSu:
+          self.sendCmds([{ 'cmd': '%s %s' % (cmd, cmdline) }], outputfile, timeout)
+        else:
+          # need to manually inject su -c for backwards compatibility (this may
+          # not work on ICS or above!!)
+          # (FIXME: this backwards compatibility code is really ugly and should
+          # be deprecated at some point in the future)
+          self.sendCmds([ { 'cmd': '%s su -c "%s"' % (cmd, cmdline) }], outputfile,
+                          timeout)
     except AgentError:
       return None
 
     # dig through the output to get the return code
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('return code \[([0-9]+)\]', lastline)
       if m:
--- a/build/mobile/robocop/FennecNativeActions.java.in
+++ b/build/mobile/robocop/FennecNativeActions.java.in
@@ -119,16 +119,17 @@ public class FennecNativeActions impleme
                 try {
                     this.wait(MAX_WAIT_MS);
                 } catch (InterruptedException ie) {
                     FennecNativeDriver.log(LogLevel.ERROR, ie);
                     break;
                 }
                 endTime = SystemClock.uptimeMillis();
                 if (!mEventReceived && (endTime - startTime >= MAX_WAIT_MS)) {
+                    FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
                     mAsserter.ok(false, "GeckoEventExpecter", 
                         "blockForEvent timeout: "+mGeckoEvent);
                     return;
                 }
             }
             try {
                 mUnregisterEventListener.invoke(mRobocopApi, mRegistrationParams);
             } catch (IllegalAccessException e) {
@@ -151,16 +152,17 @@ public class FennecNativeActions impleme
                 try {
                     this.wait(MAX_WAIT_MS);
                 } catch (InterruptedException ie) {
                     FennecNativeDriver.log(LogLevel.ERROR, ie);
                     break;
                 }
                 endTime = SystemClock.uptimeMillis();
                 if (!mEventReceived && (endTime - startTime >= MAX_WAIT_MS)) {
+                    FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
                     mAsserter.ok(false, "GeckoEventExpecter", "blockUtilClear timeout");
                     return;
                 }
             }
             // now wait for a period of millis where we don't get an event
             startTime = SystemClock.uptimeMillis();
             while (true) {
                 try {
@@ -281,16 +283,17 @@ public class FennecNativeActions impleme
                 try {
                     this.wait(MAX_WAIT_MS);
                 } catch (InterruptedException ie) {
                     FennecNativeDriver.log(LogLevel.ERROR, ie);
                     break;
                 }
                 endTime = SystemClock.uptimeMillis();
                 if (!mPaintDone && (endTime - startTime >= MAX_WAIT_MS)) {
+                    FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
                     mAsserter.ok(false, "PaintExpecter", "blockForEvent timeout");
                     return;
                 }
             }
             try {
                 mSetDrawListener.invoke(mRobocopApi, (Object)null);
             } catch (Exception e) {
                 FennecNativeDriver.log(LogLevel.ERROR, e);
@@ -312,16 +315,17 @@ public class FennecNativeActions impleme
                 try {
                     this.wait(MAX_WAIT_MS);
                 } catch (InterruptedException ie) {
                     FennecNativeDriver.log(LogLevel.ERROR, ie);
                     break;
                 }
                 endTime = SystemClock.uptimeMillis();
                 if (!mPaintDone && (endTime - startTime >= MAX_WAIT_MS)) {
+                    FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
                     mAsserter.ok(false, "PaintExpecter", "blockUtilClear timeout");
                     return;
                 }
             }
             // now wait for a period of millis where we don't get an event
             startTime = SystemClock.uptimeMillis();
             while (true) {
                 try {
--- a/build/mobile/sutagent/android/CmdWorkerThread.java
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -93,17 +93,17 @@ public class CmdWorkerThread extends Thr
         try {
             OutputStream cmdOut = socket.getOutputStream();
             InputStream cmdIn = socket.getInputStream();
             PrintWriter out = new PrintWriter(cmdOut, true);
             BufferedInputStream in = new BufferedInputStream(cmdIn);
             String inputLine, outputLine;
             DoCommand dc = new DoCommand(theParent.svc);
 
-            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread starts: "+getId());
+            SUTAgentAndroid.log(dc, "CmdWorkerThread starts: "+getId());
 
             int nAvail = cmdIn.available();
             cmdIn.skip(nAvail);
 
             out.print(prompt);
             out.flush();
 
             while (bListening)
@@ -131,17 +131,17 @@ public class CmdWorkerThread extends Thr
                     }
                 else
                     inputLine = "";
 
                 if ((inputLine += readLine(in)) != null)
                     {
                     String message = String.format("%s : %s",
                                      socket.getInetAddress().getHostAddress(), inputLine);
-                    SUTAgentAndroid.logToFile(dc, message);
+                    SUTAgentAndroid.log(dc, message);
 
                     outputLine = dc.processCommand(inputLine, out, in, cmdOut);
                     if (outputLine.length() > 0)
                         {
                         out.print(outputLine + "\n" + prompt);
                         }
                     else
                         out.print(prompt);
@@ -161,17 +161,17 @@ public class CmdWorkerThread extends Thr
                 else
                     break;
                 }
             out.close();
             out = null;
             in.close();
             in = null;
             socket.close();
-            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread ends: "+getId());
+            SUTAgentAndroid.log(dc, "CmdWorkerThread ends: "+getId());
         }
     catch (IOException e)
         {
         // TODO Auto-generated catch block
         e.printStackTrace();
         }
     }
 }
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -79,16 +79,17 @@ import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Debug;
 import android.os.Environment;
 import android.os.StatFs;
 import android.os.SystemClock;
+import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Surface;
 import android.view.WindowManager;
 
 public class DoCommand {
 
     String lineSep = System.getProperty("line.separator");
@@ -101,23 +102,25 @@ public class DoCommand {
 
     String    currentDir = "/";
     String    sErrorPrefix = "##AGENT-WARNING## ";
     boolean bTraceOn = false;
 
     String ffxProvider = "org.mozilla.ffxcp";
     String fenProvider = "org.mozilla.fencp";
 
-    private final String prgVersion = "SUTAgentAndroid Version 1.11";
+    private final String prgVersion = "SUTAgentAndroid Version 1.13";
 
     public enum Command
         {
         RUN ("run"),
         EXEC ("exec"),
+        EXECSU ("execsu"),
         EXECCWD ("execcwd"),
+        EXECCWDSU ("execcwdsu"),
         ENVRUN ("envrun"),
         KILL ("kill"),
         PS ("ps"),
         DEVINFO ("info"),
         OS ("os"),
         ID ("id"),
         UPTIME ("uptime"),
         UPTIMEMILLIS ("uptimemillis"),
@@ -678,17 +681,35 @@ public class DoCommand {
                     {
                     String [] theArgs = new String [Argc - 1];
 
                     for (int lcv = 1; lcv < Argc; lcv++)
                         {
                         theArgs[lcv - 1] = Argv[lcv];
                         }
 
-                    strReturn = StartPrg2(theArgs, cmdOut, null);
+                    strReturn = StartPrg2(theArgs, cmdOut, null, false);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECSU:
+                if (Argc >= 2)
+                    {
+                    String [] theArgs = new String [Argc - 1];
+
+                    for (int lcv = 1; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 1] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, null, true);
                     }
                 else
                     {
                     strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
                     }
                 break;
 
             case EXECCWD:
@@ -696,17 +717,35 @@ public class DoCommand {
                     {
                     String [] theArgs = new String [Argc - 2];
 
                     for (int lcv = 2; lcv < Argc; lcv++)
                         {
                         theArgs[lcv - 2] = Argv[lcv];
                         }
 
-                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1]);
+                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1], false);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECCWDSU:
+                if (Argc >= 3)
+                    {
+                    String [] theArgs = new String [Argc - 2];
+
+                    for (int lcv = 2; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 2] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1], true);
                     }
                 else
                     {
                     strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
                     }
                 break;
 
             case RUN:
@@ -715,17 +754,17 @@ public class DoCommand {
                     String [] theArgs = new String [Argc - 1];
 
                     for (int lcv = 1; lcv < Argc; lcv++)
                         {
                         theArgs[lcv - 1] = Argv[lcv];
                         }
 
                     if (Argv[1].contains("/") || Argv[1].contains("\\") || !Argv[1].contains("."))
-                        strReturn = StartPrg(theArgs, cmdOut);
+                        strReturn = StartPrg(theArgs, cmdOut, false);
                     else
                         strReturn = StartJavaPrg(theArgs, null);
                     }
                 else
                     {
                     strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
                     }
                 break;
@@ -855,35 +894,39 @@ private void CancelNotification()
         workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim();
 
         while ((nLength = workingString.length()) > 0)
             {
             int nEnd = 0;
             int    nStart = 0;
 
             // if we have a quote
-            if (workingString.startsWith("\""))
+            if (workingString.startsWith("\"") || workingString.startsWith("'"))
                 {
+                char quoteChar = '"';
+                if (workingString.startsWith("\'"))
+                    quoteChar = '\'';
+
                 // point to the first non quote char
                 nStart = 1;
                 // find the matching quote
-                nEnd = workingString.indexOf('"', nStart);
+                nEnd = workingString.indexOf(quoteChar, nStart);
 
                 char prevChar;
 
                 while(nEnd != -1)
                     {
                     // check to see if the quotation mark has been escaped
                     prevChar = workingString.charAt(nEnd - 1);
                     if (prevChar == '\\')
                         {
                         // if escaped, point past this quotation mark and find the next
                         nEnd++;
                         if (nEnd < nLength)
-                            nEnd = workingString.indexOf('"', nEnd);
+                            nEnd = workingString.indexOf(quoteChar, nEnd);
                         else
                             nEnd = -1;
                         }
                     else
                         break;
                     }
 
                 // there isn't one
@@ -904,26 +947,21 @@ private void CancelNotification()
                 // there isn't one of those
                 if (nEnd == -1)
                     nEnd = nLength;    // Just grab the rest of the cmdline
                 }
 
             // get the substring
             workingString2 = workingString.substring(nStart, nEnd);
 
-            // if we have escaped quotes
-            if (workingString2.contains("\\\""))
+            // if we have escaped quotes, convert them into standard ones
+            while (workingString2.contains("\\\"") || workingString2.contains("\\'"))
                 {
-                do
-                    {
-                    // replace escaped quote with embedded quote
-                    workingString3 = workingString2.replace("\\\"", "\"");
-                    workingString2 = workingString3;
-                    }
-                while(workingString2.contains("\\\""));
+                    workingString2 = workingString2.replace("\\\"", "\"");
+                    workingString2 = workingString2.replace("\\'", "'");
                 }
 
             // add it to the list
             lst.add(new String(workingString2));
 
             // if we are dealing with a quote
             if (nStart > 0)
                 nEnd++; //  point past the end one
@@ -3512,24 +3550,45 @@ private void CancelNotification()
         catch (InterruptedException e) {
             e.printStackTrace();
         }
 
         ctx = null;
         return (sRet);
         }
 
-    public String StartPrg(String [] progArray, OutputStream out)
+    public String StartPrg(String [] progArray, OutputStream out, boolean startAsRoot)
         {
         String sRet = "";
         int    lcv = 0;
 
-        try
-            {
-            pProc = Runtime.getRuntime().exec(progArray);
+        try {
+            if (startAsRoot)
+                {
+                    // we need to requote the program string here, in case
+                    // there's spaces or other characters which need quoting
+                    // before being passed to su
+                    List<String> quotedProgList = new ArrayList<String>();
+                    for (String arg : progArray)
+                        {
+                            String quotedArg = arg;
+                            quotedArg = quotedArg.replace("\"", "\\\"");
+                            quotedArg = quotedArg.replace("\'", "\\\'");
+                            if (quotedArg.contains(" "))
+                                {
+                                    quotedArg = "\"" + quotedArg + "\"";
+                                }
+                            quotedProgList.add(quotedArg);
+                        }
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs(TextUtils.join(" ", quotedProgList)));
+                }
+            else
+                {
+                    pProc = Runtime.getRuntime().exec(progArray);
+                }
             RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
             outThrd.start();
             while (lcv < 30) {
                 try {
                     outThrd.join(10000);
                     int nRetCode = pProc.exitValue();
                     sRet = "return code [" + nRetCode + "]";
                     break;
@@ -3547,31 +3606,31 @@ private void CancelNotification()
             {
             e.printStackTrace();
             sRet = "Timed out!";
             }
 
         return (sRet);
         }
 
-    public String StartPrg2(String [] progArray, OutputStream out, String cwd)
+    public String StartPrg2(String [] progArray, OutputStream out, String cwd, boolean startAsRoot)
         {
         String sRet = "";
 
         int    nArraySize = 0;
         int    nArgs = progArray.length - 1; // 1st arg is the environment string
         int    lcv    = 0;
         int    temp = 0;
 
         String sEnvString = progArray[0];
 
         if (!sEnvString.contains("=") && (sEnvString.length() > 0))
             {
             if (sEnvString.contains("/") || sEnvString.contains("\\") || !sEnvString.contains("."))
-                sRet = StartPrg(progArray, out);
+                sRet = StartPrg(progArray, out, startAsRoot);
             else
                 sRet = StartJavaPrg(progArray, null);
             return(sRet);
             }
 
         // Set up command line args stripping off the environment string
         String [] theArgs = new String [nArgs];
         for (lcv = 0; lcv < nArgs; lcv++)
@@ -3767,70 +3826,73 @@ private void CancelNotification()
         }
 
         return(sRet);
         }
 
     private String PrintUsage()
         {
         String sRet =
-            "run [cmdline]                - start program no wait\n" +
-            "exec [env pairs] [cmdline]   - start program no wait optionally pass env\n" +
-            "                               key=value pairs (comma separated)\n" +
-            "kill [program name]          - kill program no path\n" +
-            "killall                      - kill all processes started\n" +
-            "ps                           - list of running processes\n" +
-            "info                         - list of device info\n" +
-            "        [os]                 - os version for device\n" +
-            "        [id]                 - unique identifier for device\n" +
-            "        [uptime]             - uptime for device\n" +
-            "        [uptimemillis]       - uptime for device in milliseconds\n" +
-            "        [systime]            - current system time\n" +
-            "        [screen]             - width, height and bits per pixel for device\n" +
-            "        [memory]             - physical, free, available, storage memory\n" +
-            "                               for device\n" +
-            "        [processes]          - list of running processes see 'ps'\n" +
-            "deadman timeout              - set the duration for the deadman timer\n" +
-            "alrt [on/off]                - start or stop sysalert behavior\n" +
-            "disk [arg]                   - prints disk space info\n" +
-            "cp file1 file2               - copy file1 to file2\n" +
-            "time file                    - timestamp for file\n" +
-            "hash file                    - generate hash for file\n" +
-            "cd directory                 - change cwd\n" +
-            "cat file                     - cat file\n" +
-            "cwd                          - display cwd\n" +
-            "mv file1 file2               - move file1 to file2\n" +
-            "push filename                - push file to device\n" +
-            "rm file                      - delete file\n" +
-            "rmdr directory               - delete directory even if not empty\n" +
-            "mkdr directory               - create directory\n" +
-            "dirw directory               - tests whether the directory is writable\n" +
-            "isdir directory              - test whether the directory exists\n" +
-            "chmod directory|file         - change permissions of directory and contents (or file) to 777\n" +
-            "stat processid               - stat process\n" +
-            "dead processid               - print whether the process is alive or hung\n" +
-            "mems                         - dump memory stats\n" +
-            "ls                           - print directory\n" +
-            "tmpd                         - print temp directory\n" +
-            "ping [hostname/ipaddr]       - ping a network device\n" +
-            "unzp zipfile destdir         - unzip the zipfile into the destination dir\n" +
-            "zip zipfile src              - zip the source file/dir into zipfile\n" +
-            "rebt                         - reboot device\n" +
-            "inst /path/filename.apk      - install the referenced apk file\n" +
-            "uninst packagename           - uninstall the referenced package and reboot\n" +
-            "uninstall packagename        - uninstall the referenced package without a reboot\n" +
-            "updt pkgname pkgfile         - unpdate the referenced package\n" +
-            "clok                         - the current device time expressed as the" +
-            "                               number of millisecs since epoch\n" +
-            "settime date time            - sets the device date and time\n" +
-            "                               (YYYY/MM/DD HH:MM:SS)\n" +
-            "tzset timezone               - sets the device timezone format is\n" +
-            "                               GMTxhh:mm x = +/- or a recognized Olsen string\n" +
-            "tzget                        - returns the current timezone set on the device\n" +
-            "rebt                         - reboot device\n" +
-            "adb ip|usb                   - set adb to use tcp/ip on port 5555 or usb\n" +
-            "quit                         - disconnect SUTAgent\n" +
-            "exit                         - close SUTAgent\n" +
-            "ver                          - SUTAgent version\n" +
-            "help                         - you're reading it";
+            "run [cmdline]                   - start program no wait\n" +
+            "exec [env pairs] [cmdline]      - start program no wait optionally pass env\n" +
+            "                                  key=value pairs (comma separated)\n" +
+            "execcwd [env pairs] [cmdline]   - start program from specified directory\n" +
+            "execsu [env pairs] [cmdline]    - start program as privileged user\n" +
+            "execcwdsu [env pairs] [cmdline] - start program from specified directory as privileged user\n" +
+            "kill [program name]             - kill program no path\n" +
+            "killall                         - kill all processes started\n" +
+            "ps                              - list of running processes\n" +
+            "info                            - list of device info\n" +
+            "        [os]                    - os version for device\n" +
+            "        [id]                    - unique identifier for device\n" +
+            "        [uptime]                - uptime for device\n" +
+            "        [uptimemillis]          - uptime for device in milliseconds\n" +
+            "        [systime]               - current system time\n" +
+            "        [screen]                - width, height and bits per pixel for device\n" +
+            "        [memory]                - physical, free, available, storage memory\n" +
+            "                                  for device\n" +
+            "        [processes]             - list of running processes see 'ps'\n" +
+            "deadman timeout                 - set the duration for the deadman timer\n" +
+            "alrt [on/off]                   - start or stop sysalert behavior\n" +
+            "disk [arg]                      - prints disk space info\n" +
+            "cp file1 file2                  - copy file1 to file2\n" +
+            "time file                       - timestamp for file\n" +
+            "hash file                       - generate hash for file\n" +
+            "cd directory                    - change cwd\n" +
+            "cat file                        - cat file\n" +
+            "cwd                             - display cwd\n" +
+            "mv file1 file2                  - move file1 to file2\n" +
+            "push filename                   - push file to device\n" +
+            "rm file                         - delete file\n" +
+            "rmdr directory                  - delete directory even if not empty\n" +
+            "mkdr directory                  - create directory\n" +
+            "dirw directory                  - tests whether the directory is writable\n" +
+            "isdir directory                 - test whether the directory exists\n" +
+            "chmod directory|file            - change permissions of directory and contents (or file) to 777\n" +
+            "stat processid                  - stat process\n" +
+            "dead processid                  - print whether the process is alive or hung\n" +
+            "mems                            - dump memory stats\n" +
+            "ls                              - print directory\n" +
+            "tmpd                            - print temp directory\n" +
+            "ping [hostname/ipaddr]          - ping a network device\n" +
+            "unzp zipfile destdir            - unzip the zipfile into the destination dir\n" +
+            "zip zipfile src                 - zip the source file/dir into zipfile\n" +
+            "rebt                            - reboot device\n" +
+            "inst /path/filename.apk         - install the referenced apk file\n" +
+            "uninst packagename              - uninstall the referenced package and reboot\n" +
+            "uninstall packagename           - uninstall the referenced package without a reboot\n" +
+            "updt pkgname pkgfile            - unpdate the referenced package\n" +
+            "clok                            - the current device time expressed as the" +
+            "                                  number of millisecs since epoch\n" +
+            "settime date time               - sets the device date and time\n" +
+            "                                  (YYYY/MM/DD HH:MM:SS)\n" +
+            "tzset timezone                  - sets the device timezone format is\n" +
+            "                                  GMTxhh:mm x = +/- or a recognized Olsen string\n" +
+            "tzget                           - returns the current timezone set on the device\n" +
+            "rebt                            - reboot device\n" +
+            "adb ip|usb                      - set adb to use tcp/ip on port 5555 or usb\n" +
+            "quit                            - disconnect SUTAgent\n" +
+            "exit                            - close SUTAgent\n" +
+            "ver                             - SUTAgent version\n" +
+            "help                            - you're reading it";
         return (sRet);
         }
 }
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -161,17 +161,17 @@ public class SUTAgentAndroid extends Act
         String lc = dc.GetIniData("General", "LogCommands", sIniFile);
         if (lc != "" && Integer.parseInt(lc) == 1) {
             SUTAgentAndroid.LogCommands = true;
         }
         SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
         SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
         SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
         SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
-        logToFile(dc, "onCreate");
+        log(dc, "onCreate");
 
         tv = (TextView) this.findViewById(R.id.Textview01);
 
         if (getLocalIpAddress() == null)
             setUpNetwork(sIniFile);
 
         String macAddress = "Unknown";
         if (android.os.Build.VERSION.SDK_INT > 8) {
@@ -357,57 +357,57 @@ public class SUTAgentAndroid extends Act
 
     @Override
     public void onDestroy()
         {
         DoCommand dc = new DoCommand(getApplication());
         super.onDestroy();
         if (isFinishing())
             {
-            logToFile(dc, "onDestroy - finishing");
+            log(dc, "onDestroy - finishing");
             Intent listenerSvc = new Intent(this, ASMozStub.class);
             listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
             stopService(listenerSvc);
             bNetworkingStarted = false;
 
             unregisterReceiver(battReceiver);
 
             if (wl != null)
                 wl.release();
 
             System.exit(0);
             }
         else
             {
-            logToFile(dc, "onDestroy - not finishing");
+            log(dc, "onDestroy - not finishing");
             }
         }
 
     @Override
     public void onLowMemory()
         {
         System.gc();
         DoCommand dc = new DoCommand(getApplication());
         if (dc != null)
             {
-            logToFile(dc, "onLowMemory");
-            logToFile(dc, dc.GetMemoryInfo());
+            log(dc, "onLowMemory");
+            log(dc, dc.GetMemoryInfo());
             String procInfo = dc.GetProcessInfo();
             if (procInfo != null)
                 {
                 String lines[] = procInfo.split("\n");
                 for (String line : lines) 
                     {
                     if (line.contains("mozilla"))
                         {
-                        logToFile(dc, line);
+                        log(dc, line);
                         String words[] = line.split("\t");
                         if ((words != null) && (words.length > 1))
                             {
-                            logToFile(dc, dc.StatProcess(words[1]));
+                            log(dc, dc.StatProcess(words[1]));
                             }
                         }
                     }
                 }
             }
         else
             {
             Log.e("SUTAgentAndroid", "onLowMemory: unable to log to file!");
@@ -757,35 +757,36 @@ public class SUTAgentAndroid extends Act
             }
         catch (SocketException ex)
             {
             Toast.makeText(getApplication().getApplicationContext(), ex.toString(), Toast.LENGTH_LONG).show();
             }
         return null;
         }
 
-    public static void logToFile(DoCommand dc, String message)
+    public static void log(DoCommand dc, String message)
         {
+        Log.i("SUTAgentAndroid", message);
+
         if (SUTAgentAndroid.LogCommands == false)
             {
             return;
             }
 
         if (message == null)
             {
-            Log.e("SUTAgentAndroid", "bad arguments in logToFile()!");
+            Log.e("SUTAgentAndroid", "bad arguments in log()!");
             return;
             }
-        Log.i("SUTAgentAndroid", message);
         String fileDateStr = "00";
         String testRoot = dc.GetTestRoot();
         String datestamp = dc.GetSystemTime();
         if (testRoot == null || datestamp == null)
             {
-            Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in logToFile!");
+            Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in log!");
             return;
             }
 
 
         try 
             {
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
             Date dateStr = sdf.parse(datestamp);
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -25,16 +25,19 @@
 #include "nsContentUtils.h"
 #include "jswrapper.h"
 
 #include "nsPrincipal.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/HashFunctions.h"
 
+#include "nsIAppsService.h"
+#include "mozIApplication.h"
+
 using namespace mozilla;
 
 static bool gCodeBasePrincipalSupport = false;
 static bool gIsObservingCodeBasePrincipalSupport = false;
 
 static bool URIIsImmutable(nsIURI* aURI)
 {
   nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
@@ -1294,20 +1297,55 @@ nsPrincipal::Write(nsIObjectOutputStream
 
 uint16_t
 nsPrincipal::GetAppStatus()
 {
   MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
 
   // Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID)
   // and they are not inside a mozbrowser.
-  return mAppId != nsIScriptSecurityManager::NO_APP_ID &&
-         mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID && !mInMozBrowser
-          ? nsIPrincipal::APP_STATUS_INSTALLED
-          : nsIPrincipal::APP_STATUS_NOT_INSTALLED;
+  if (mAppId == nsIScriptSecurityManager::NO_APP_ID ||
+      mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID || mInMozBrowser) {
+    return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
+  }
+
+  nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  nsCOMPtr<mozIDOMApplication> domApp;
+  appsService->GetAppByLocalId(mAppId, getter_AddRefs(domApp));
+  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
+  NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED;
+  NS_ENSURE_SUCCESS(app->GetAppStatus(&status),
+                    nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  nsCAutoString origin;
+  NS_ENSURE_SUCCESS(GetOrigin(getter_Copies(origin)),
+                    nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+  nsString appOrigin;
+  NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin),
+                    nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  // We go from string -> nsIURI -> origin to be sure we
+  // compare two punny-encoded origins.
+  nsCOMPtr<nsIURI> appURI;
+  NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin),
+                    nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  nsCAutoString appOriginPunned;
+  NS_ENSURE_SUCCESS(GetOriginForURI(appURI, getter_Copies(appOriginPunned)),
+                    nsIPrincipal::APP_STATUS_NOT_INSTALLED);
+
+  if (!appOriginPunned.Equals(origin)) {
+    return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
+  }
+
+  return status;
 }
 
 /************************************************************************************************************************/
 
 static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
 
 NS_IMPL_CLASSINFO(nsExpandedPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_EXPANDEDPRINCIPAL_CID)
--- a/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
+++ b/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
@@ -8,17 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for nsIPrincipal extendedOrigin, appStatus and appId</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=758258">Mozilla Bug 758258</a>
 <p id="display"></p>
 <div id="content">
-  
+
 </div>
 <pre id="test">
 <script type="application/javascript;version=1.7">
 
 /** Test for Bug 758258 **/
 
 var Ci = Components.interfaces;
 
@@ -124,23 +124,23 @@ var gData = [
     src: "file:///tmp/",
     isapp: false,
     test: [ "eo-unique" ],
   },
   {
     app: "http://example.org/manifest.webapp",
     src: "file:///",
     isapp: true,
-    test: [ "eo-unique" ],
+    test: [ "eo-unique", "in-app-not-installed" ],
   },
   {
     app: "http://example.org/manifest.webapp",
     src: "file:///tmp/",
     isapp: true,
-    test: [ "eo-unique" ],
+    test: [ "eo-unique", "in-app-not-installed" ],
   },
   // iframe inside an app is part of the app.
   {
     app: "http://example.org/manifest.webapp",
     src: "http://example.org/",
     isapp: true,
     child: {
       src: "http://example.org/chrome/",
@@ -276,22 +276,21 @@ function checkIFrame(aFrame, data) {
        data.src.replace('file:///tmp/', 'file:///private/tmp/'),
        'the correct URL should have been loaded');
   } else {
     is(principal.URI.spec, data.src,
        'the correct URL should have been loaded');
   }
 
   if (data.isapp) {
-    is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED,
-       'this should be an installed app');
-    isnot(principal.appId, Ci.nsIScriptSecurityManager.NO_APP_ID,
-          "installed app should have a valid appId");
-    isnot(principal.appId, Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID,
-          "installed app should have a valid appId");
+    if (data.test.indexOf("in-app-not-installed") != -1) {
+      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED, 'this should not be an installed app');
+    } else {
+      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED, 'this should be an installed app');
+    }
   } else {
     is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED,
        'this should not be an installed app');
     is(principal.appId, Ci.nsIScriptSecurityManager.NO_APP_ID,
        "principals from non-installed app should have NO_APP_ID");
   }
 
   if (!data.isapp && !data.browser) {
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1131,17 +1131,17 @@ ifdef SUBMAKEFILES
 $(SUBMAKEFILES): % : $(srcdir)/%.in
 	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file=$@
 	@$(TOUCH) $@
 endif
 endif
 
 ifdef AUTOUPDATE_CONFIGURE
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck)
+	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
 endif
 
 $(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
 	$(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
 	$(TOUCH) $@
 
 ###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
@@ -1495,17 +1495,17 @@ endif
 #   a previous build in the source tree) and thus neglect to create a
 #   dependency directory in the object directory, where we really need
 #   it.
 
 $(CURDIR)/$(MDDEPDIR):
 	$(MKDIR) -p $@
 
 ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
-MDDEPEND_FILES		:= $(strip $(wildcard $(MDDEPDIR)/*.pp))
+MDDEPEND_FILES		:= $(strip $(wildcard $(foreach file,$(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS) $(TARGETS) $(XPIDLSRCS:.idl=.h) $(XPIDLSRCS:.idl=.xpt),$(MDDEPDIR)/$(notdir $(file)).pp) $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
 
 ifneq (,$(MDDEPEND_FILES))
 # The script mddepend.pl checks the dependencies and writes to stdout
 # one rule to force out-of-date objects. For example,
 #   foo.o boo.o: FORCE
 # The script has an advantage over including the *.pp files directly
 # because it handles the case when header files are removed from the build.
 # 'make' would complain that there is no way to build missing headers.
--- a/config/system-headers
+++ b/config/system-headers
@@ -1062,8 +1062,12 @@ nestegg/nestegg.h
 cubeb/cubeb.h
 #endif
 gst/gst.h
 gst/app/gstappsink.h
 gst/app/gstappsrc.h
 gst/video/video.h
 sys/msg.h
 sys/ipc.h
+sys/thr.h
+sys/user.h
+kvm.h
+spawn.h
--- a/configure.in
+++ b/configure.in
@@ -3210,17 +3210,18 @@ then
     LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}"
 fi
 
 
 dnl Checks for library functions.
 dnl ========================================================
 AC_PROG_GCC_TRADITIONAL
 AC_FUNC_MEMCMP
-AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat64 lstat64 truncate64 statvfs64 setbuf isatty)
+AC_CHECK_FUNCS(random strerror lchown fchmod snprintf memmove rint stat64 lstat64 truncate64 setbuf isatty)
+AC_CHECK_FUNCS(statvfs64 statvfs statfs64 statfs)
 AC_CHECK_FUNCS(flockfile getpagesize)
 AC_CHECK_FUNCS(localtime_r strtok_r)
 
 dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
 AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
                ac_cv_clock_monotonic,
                [for libs in "" -lrt; do
                     _SAVE_LIBS="$LIBS"
@@ -4193,16 +4194,17 @@ NECKO_PROTOCOLS_DEFAULT="about data file
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_GRAPHITE=1
 ACCESSIBILITY=1
 MOZ_SYS_MSG=
+MOZ_PAY=
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -7307,16 +7309,24 @@ MOZ_ARG_ENABLE_BOOL(b2g-camera,
     MOZ_B2G_CAMERA=1,
     MOZ_B2G_CAMERA= )
 if test -n "$MOZ_B2G_CAMERA"; then
    AC_DEFINE(MOZ_B2G_CAMERA)
 fi
 AC_SUBST(MOZ_B2G_CAMERA)
 
 dnl ========================================================
+dnl = Enable Support for Payment API
+dnl ========================================================
+if test -n "$MOZ_PAY"; then
+    AC_DEFINE(MOZ_PAY)
+fi
+AC_SUBST(MOZ_PAY)
+
+dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
     AC_LANG_CPLUSPLUS
     AC_CHECK_FUNCS(__cxa_demangle, HAVE_DEMANGLE=1, HAVE_DEMANGLE=)
     AC_LANG_RESTORE
 fi
@@ -8595,27 +8605,31 @@ dnl The following defines are used by xp
 _NON_GLOBAL_ACDEFINES="$_NON_GLOBAL_ACDEFINES
 CPP_THROW_NEW
 HAVE_CPP_2BYTE_WCHAR_T
 HAVE_CPP_AMBIGUITY_RESOLVING_USING
 HAVE_CPP_CHAR16_T
 HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
 HAVE_CPP_PARTIAL_SPECIALIZATION
 HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
-HAVE_STATVFS
-HAVE_STATVFS64
 NEED_CPP_UNUSED_IMPLEMENTATIONS
 NEW_H
 HAVE_GETPAGESIZE
 HAVE_ICONV
 HAVE_ICONV_WITH_CONST_INPUT
 HAVE_MBRTOWC
-HAVE_SYS_MOUNT_H
+HAVE_WCRTOMB
+HAVE_STATVFS64
+HAVE_STATVFS
+HAVE_STATFS64
+HAVE_STATFS
+HAVE_SYS_STATVFS_H
+HAVE_SYS_STATFS_H
 HAVE_SYS_VFS_H
-HAVE_WCRTOMB
+HAVE_SYS_MOUNT_H
 "
 
 AC_CONFIG_HEADER(
 netwerk/necko-config.h
 xpcom/xpcom-config.h
 xpcom/xpcom-private.h
 )
 
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -11,17 +11,16 @@
 
 #ifndef FragmentOrElement_h___
 #define FragmentOrElement_h___
 
 #include "nsAttrAndChildArray.h"          // member
 #include "nsCOMPtr.h"                     // member
 #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
 #include "nsIContent.h"                   // base class
-#include "nsIDOMNodeSelector.h"           // base class
 #include "nsIDOMTouchEvent.h"             // base class (nsITouchEventReceiver)
 #include "nsIDOMXPathNSResolver.h"        // base class
 #include "nsIInlineEventHandlers.h"       // base class
 #include "nsINodeList.h"                  // base class
 #include "nsIWeakReference.h"             // base class
 #include "nsNodeUtils.h"                  // class member nsNodeUtils::CloneNodeImpl
 
 class ContentUnbinder;
@@ -149,39 +148,16 @@ public:
   NS_DECL_NSISUPPORTSWEAKREFERENCE
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSupportsWeakRefTearoff)
 
 private:
   nsCOMPtr<nsINode> mNode;
 };
 
-/**
- * A tearoff class for FragmentOrElement to implement NodeSelector
- */
-class nsNodeSelectorTearoff MOZ_FINAL : public nsIDOMNodeSelector
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-
-  NS_DECL_NSIDOMNODESELECTOR
-
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSelectorTearoff)
-
-  nsNodeSelectorTearoff(nsINode *aNode) : mNode(aNode)
-  {
-  }
-
-private:
-  ~nsNodeSelectorTearoff() {}
-
-private:
-  nsCOMPtr<nsINode> mNode;
-};
-
 // Forward declare to allow being a friend
 class nsTouchEventReceiverTearoff;
 class nsInlineEventHandlersTearoff;
 
 /**
  * A generic base class for DOM elements, implementing many nsIContent,
  * nsIDOMNode and nsIDOMElement methods.
  */
@@ -302,25 +278,16 @@ public:
   /**
    * If there are listeners for DOMNodeInserted event, fires the event on all
    * aNodes
    */
   static void FireNodeInserted(nsIDocument* aDoc,
                                nsINode* aParent,
                                nsTArray<nsCOMPtr<nsIContent> >& aNodes);
 
-  /**
-   * Helper methods for implementing querySelector/querySelectorAll
-   */
-  static nsIContent* doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
-                                     nsresult *aResult);
-  static nsresult doQuerySelectorAll(nsINode* aRoot,
-                                     const nsAString& aSelector,
-                                     nsIDOMNodeList **aReturn);
-
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(FragmentOrElement)
 
   /**
    * Fire a DOMNodeRemoved mutation event for all children of this node
    */
   void FireNodeRemovedForChildren();
 
   virtual bool OwnedOnlyByTheDOMTree()
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsINode_h___
 #define nsINode_h___
 
 #include "nsCOMPtr.h"               // for member, local
 #include "nsGkAtoms.h"              // for nsGkAtoms::baseURIProperty
 #include "nsIDOMEventTarget.h"      // for base class
+#include "nsIDOMNodeSelector.h"     // base class
 #include "nsINodeInfo.h"            // member (in nsCOMPtr)
 #include "nsIVariant.h"             // for use in GetUserData()
 #include "nsNodeInfoManager.h"      // for use in NodePrincipal()
 #include "nsPropertyTable.h"        // for typedefs
 #include "nsTObserverArray.h"       // for member
 #include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS
 #include "nsWrapperCache.h"         // for base class
 
@@ -1047,16 +1048,24 @@ public:
     return NS_OK;
   }
   NS_IMETHOD SetTextContent(const nsAString& aTextContent)
   {
     return NS_OK;
   }
 
   /**
+   * Helper methods for implementing querySelector/querySelectorAll
+   */
+  nsIContent* QuerySelector(const nsAString& aSelector,
+                            nsresult *aResult);
+  nsresult QuerySelectorAll(const nsAString& aSelector,
+                            nsIDOMNodeList **aReturn);
+
+  /**
    * Associate an object aData to aKey on this node. If aData is null any
    * previously registered object and UserDataHandler associated to aKey on
    * this node will be removed.
    * Should only be used to implement the DOM Level 3 UserData API.
    *
    * @param aKey the key to associate the object to
    * @param aData the object to associate to aKey on this node (may be null)
    * @param aHandler the UserDataHandler to call when the node is
@@ -1566,16 +1575,38 @@ protected:
 template<class C, class D>
 inline nsINode* NODE_FROM(C& aContent, D& aDocument)
 {
   if (aContent)
     return static_cast<nsINode*>(aContent);
   return static_cast<nsINode*>(aDocument);
 }
 
+/**
+ * A tearoff class for FragmentOrElement to implement NodeSelector
+ */
+class nsNodeSelectorTearoff MOZ_FINAL : public nsIDOMNodeSelector
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+  NS_DECL_NSIDOMNODESELECTOR
+
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSelectorTearoff)
+
+  nsNodeSelectorTearoff(nsINode *aNode) : mNode(aNode)
+  {
+  }
+
+private:
+  ~nsNodeSelectorTearoff() {}
+
+private:
+  nsCOMPtr<nsINode> mNode;
+};
 
 extern const nsIID kThisPtrOffsetsSID;
 
 // _implClass is the class to use to cast to nsISupports
 #define NS_OFFSET_AND_INTERFACE_TABLE_BEGIN_AMBIGUOUS(_class, _implClass)     \
   static const QITableEntry offsetAndQITable[] = {                            \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _implClass)
 
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -91,32 +91,30 @@
 #include "nsEventDispatcher.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIControllers.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsXBLInsertionPoint.h"
 #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
-#include "nsCSSRuleProcessor.h"
 #include "nsRuleProcessorData.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsTextNode.h"
 #include "dombindings.h"
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif /* MOZ_XUL */
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
-#include "nsCSSParser.h"
 #include "prprf.h"
 #include "nsDOMMutationObserver.h"
 #include "nsSVGFeatures.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsCycleCollector.h"
 #include "xpcpublic.h"
 #include "nsIScriptError.h"
 #include "nsLayoutStatics.h"
@@ -514,43 +512,16 @@ nsNodeSupportsWeakRefTearoff::GetWeakRef
 
   NS_ADDREF(*aInstancePtr = slots->mWeakReference);
 
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 
-NS_IMPL_CYCLE_COLLECTION_1(nsNodeSelectorTearoff, mNode)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSelectorTearoff)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMNodeSelector)
-NS_INTERFACE_MAP_END_AGGREGATED(mNode)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSelectorTearoff)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSelectorTearoff)
-
-NS_IMETHODIMP
-nsNodeSelectorTearoff::QuerySelector(const nsAString& aSelector,
-                                     nsIDOMElement **aReturn)
-{
-  nsresult rv;
-  nsIContent* result = FragmentOrElement::doQuerySelector(mNode, aSelector, &rv);
-  return result ? CallQueryInterface(result, aReturn) : rv;
-}
-
-NS_IMETHODIMP
-nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
-                                        nsIDOMNodeList **aReturn)
-{
-  return FragmentOrElement::doQuerySelectorAll(mNode, aSelector, aReturn);
-}
-
-//----------------------------------------------------------------------
-
 NS_IMPL_CYCLE_COLLECTION_1(nsTouchEventReceiverTearoff, mElement)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTouchEventReceiverTearoff)
   NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
 NS_INTERFACE_MAP_END_AGGREGATED(mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTouchEventReceiverTearoff)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTouchEventReceiverTearoff)
@@ -1971,172 +1942,14 @@ FragmentOrElement::FireNodeRemovedForChi
   nsCOMPtr<nsINode> child;
   for (child = GetFirstChild();
        child && child->GetNodeParent() == this;
        child = child->GetNextSibling()) {
     nsContentUtils::MaybeFireNodeRemoved(child, this, doc);
   }
 }
 
-// NOTE: The aPresContext pointer is NOT addrefed.
-// *aSelectorList might be null even if NS_OK is returned; this
-// happens when all the selectors were pseudo-element selectors.
-static nsresult
-ParseSelectorList(nsINode* aNode,
-                  const nsAString& aSelectorString,
-                  nsCSSSelectorList** aSelectorList)
-{
-  NS_ENSURE_ARG(aNode);
-
-  nsIDocument* doc = aNode->OwnerDoc();
-  nsCSSParser parser(doc->CSSLoader());
-
-  nsCSSSelectorList* selectorList;
-  nsresult rv = parser.ParseSelectorString(aSelectorString,
-                                           doc->GetDocumentURI(),
-                                           0, // XXXbz get the line number!
-                                           &selectorList);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Filter out pseudo-element selectors from selectorList
-  nsCSSSelectorList** slot = &selectorList;
-  do {
-    nsCSSSelectorList* cur = *slot;
-    if (cur->mSelectors->IsPseudoElement()) {
-      *slot = cur->mNext;
-      cur->mNext = nullptr;
-      delete cur;
-    } else {
-      slot = &cur->mNext;
-    }
-  } while (*slot);
-  *aSelectorList = selectorList;
-
-  return NS_OK;
-}
-
-// Actually find elements matching aSelectorList (which must not be
-// null) and which are descendants of aRoot and put them in aList.  If
-// onlyFirstMatch, then stop once the first one is found.
-template<bool onlyFirstMatch, class T>
-inline static nsresult FindMatchingElements(nsINode* aRoot,
-                                            const nsAString& aSelector,
-                                            T &aList)
-{
-  nsAutoPtr<nsCSSSelectorList> selectorList;
-  nsresult rv = ParseSelectorList(aRoot, aSelector,
-                                  getter_Transfers(selectorList));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(selectorList, NS_OK);
-
-  NS_ASSERTION(selectorList->mSelectors,
-               "How can we not have any selectors?");
-
-  nsIDocument* doc = aRoot->OwnerDoc();  
-  TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
-                                   doc, TreeMatchContext::eNeverMatchVisited);
-  doc->FlushPendingLinkUpdates();
-
-  // Fast-path selectors involving IDs.  We can only do this if aRoot
-  // is in the document and the document is not in quirks mode, since
-  // ID selectors are case-insensitive in quirks mode.  Also, only do
-  // this if selectorList only has one selector, because otherwise
-  // ordering the elements correctly is a pain.
-  NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
-               !aRoot->IsInDoc(),
-               "The optimization below to check ContentIsDescendantOf only for "
-               "elements depends on aRoot being either an element or a "
-               "document if it's in the document.");
-  if (aRoot->IsInDoc() &&
-      doc->GetCompatibilityMode() != eCompatibility_NavQuirks &&
-      !selectorList->mNext &&
-      selectorList->mSelectors->mIDList) {
-    nsIAtom* id = selectorList->mSelectors->mIDList->mAtom;
-    const nsSmallVoidArray* elements =
-      doc->GetAllElementsForId(nsDependentAtomString(id));
-
-    // XXXbz: Should we fall back to the tree walk if aRoot is not the
-    // document and |elements| is long, for some value of "long"?
-    if (elements) {
-      for (int32_t i = 0; i < elements->Count(); ++i) {
-        Element *element = static_cast<Element*>(elements->ElementAt(i));
-        if (!aRoot->IsElement() ||
-            (element != aRoot &&
-             nsContentUtils::ContentIsDescendantOf(element, aRoot))) {
-          // We have an element with the right id and it's a strict descendant
-          // of aRoot.  Make sure it really matches the selector.
-          if (nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
-                                                      selectorList)) {
-            aList.AppendElement(element);
-            if (onlyFirstMatch) {
-              return NS_OK;
-            }
-          }
-        }
-      }
-    }
-
-    // No elements with this id, or none of them are our descendants,
-    // or none of them match.  We're done here.
-    return NS_OK;
-  }
-
-  for (nsIContent* cur = aRoot->GetFirstChild();
-       cur;
-       cur = cur->GetNextNode(aRoot)) {
-    if (cur->IsElement() &&
-        nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
-                                                matchingContext,
-                                                selectorList)) {
-      aList.AppendElement(cur->AsElement());
-      if (onlyFirstMatch) {
-        return NS_OK;
-      }
-    }
-  }
-
-  return NS_OK;
-}
-
-struct ElementHolder {
-  ElementHolder() : mElement(nullptr) {}
-  void AppendElement(Element* aElement) {
-    NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
-    mElement = aElement;
-  }
-  Element* mElement;
-};
-
-/* static */
-nsIContent*
-FragmentOrElement::doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
-                                  nsresult *aResult)
-{
-  NS_PRECONDITION(aResult, "Null out param?");
-
-  ElementHolder holder;
-  *aResult = FindMatchingElements<true>(aRoot, aSelector, holder);
-
-  return holder.mElement;
-}
-
-/* static */
-nsresult
-FragmentOrElement::doQuerySelectorAll(nsINode* aRoot,
-                                     const nsAString& aSelector,
-                                     nsIDOMNodeList **aReturn)
-{
-  NS_PRECONDITION(aReturn, "Null out param?");
-
-  nsSimpleContentList* contentList = new nsSimpleContentList(aRoot);
-  NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aReturn = contentList);
-  
-  return FindMatchingElements<false>(aRoot, aSelector, *contentList);
-}
-
-
 size_t
 FragmentOrElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
   return nsIContent::SizeOfExcludingThis(aMallocSizeOf) +
          mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
 }
--- a/content/base/src/nsBlobProtocolHandler.cpp
+++ b/content/base/src/nsBlobProtocolHandler.cpp
@@ -168,17 +168,17 @@ nsBlobProtocolHandler::NewChannel(nsIURI
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
 
   nsAutoString type;
   rv = info->mFile->GetType(type);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  PRUint64 size;
+  uint64_t size;
   rv = info->mFile->GetSize(&size);
   NS_ENSURE_SUCCESS(rv, rv);
 
   channel->SetOwner(owner);
   channel->SetOriginalURI(uri);
   channel->SetContentType(NS_ConvertUTF16toUTF8(type));
   channel->SetContentLength(size);
 
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -489,17 +489,17 @@ nsDOMFileFile::GetMozFullPathInternal(ns
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   return mFile->GetPath(aFilename);
 }
 
 NS_IMETHODIMP
 nsDOMFileFile::GetLastModifiedDate(JSContext* cx, JS::Value *aLastModifiedDate)
 {
-  int64_t msecs;
+  PRTime msecs;
   mFile->GetLastModifiedTime(&msecs);
   JSObject* date = JS_NewDateObjectMsec(cx, msecs);
   if (date) {
     aLastModifiedDate->setObject(*date);
   }
   else {
     aLastModifiedDate->setNull();
   }
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -817,33 +817,43 @@ nsFrameScriptExecutor::Shutdown()
 void
 nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
 {
   if (!mGlobal || !mCx || !sCachedScripts) {
     return;
   }
 
   nsFrameJSScriptExecutorHolder* holder = sCachedScripts->Get(aURL);
+  if (!holder) {
+    TryCacheLoadAndCompileScript(aURL, EXECUTE_IF_CANT_CACHE);
+    holder = sCachedScripts->Get(aURL);
+  }
+
   if (holder) {
     nsContentUtils::ThreadJSContextStack()->Push(mCx);
     {
       // Need to scope JSAutoRequest to happen after Push but before Pop,
       // at least for now. See bug 584673.
       JSAutoRequest ar(mCx);
       JSObject* global = nullptr;
       mGlobal->GetJSObject(&global);
       if (global) {
         (void) JS_ExecuteScript(mCx, global, holder->mScript, nullptr);
       }
     }
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
     return;
   }
+}
 
+void
+nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
+                                                    CacheFailedBehavior aBehavior)
+{
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
   if (NS_FAILED(rv)) {
     return;
   }
   
   bool hasFlags;
@@ -902,18 +912,19 @@ nsFrameScriptExecutor::LoadFrameScriptIn
           // We don't cache data: scripts!
           if (!scheme.EqualsLiteral("data")) {
             nsFrameJSScriptExecutorHolder* holder =
               new nsFrameJSScriptExecutorHolder(script);
             // Root the object also for caching.
             JS_AddNamedScriptRoot(mCx, &(holder->mScript),
                                   "Cached message manager script");
             sCachedScripts->Put(aURL, holder);
+          } else if (aBehavior == EXECUTE_IF_CANT_CACHE) {
+            (void) JS_ExecuteScript(mCx, global, script, nullptr);
           }
-          (void) JS_ExecuteScript(mCx, global, script, nullptr);
         }
       }
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
 }
 
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -219,16 +219,19 @@ protected:
                             mDelayedCxDestroy(false)
   { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
   ~nsFrameScriptExecutor()
   { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
   void DidCreateCx();
   // Call this when you want to destroy mCx.
   void DestroyCx();
   void LoadFrameScriptInternal(const nsAString& aURL);
+  enum CacheFailedBehavior { EXECUTE_IF_CANT_CACHE, DONT_EXECUTE };
+  void TryCacheLoadAndCompileScript(const nsAString& aURL,
+                                    CacheFailedBehavior aBehavior = DONT_EXECUTE);
   bool InitTabChildGlobalInternal(nsISupports* aScope);
   static void Traverse(nsFrameScriptExecutor *tmp,
                        nsCycleCollectionTraversalCallback &cb);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   JSContext* mCx;
   uint32_t mCxStackRefCnt;
   bool mDelayedCxDestroy;
   nsCOMPtr<nsIPrincipal> mPrincipal;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1804,19 +1804,19 @@ nsGenericElement::LeaveLink(nsPresContex
   if (!handler) {
     return NS_OK;
   }
 
   return handler->OnLeaveLink();
 }
 
 nsresult
-nsGenericElement::AddScriptEventListener(nsIAtom* aEventName,
-                                         const nsAString& aValue,
-                                         bool aDefer)
+nsGenericElement::SetEventHandler(nsIAtom* aEventName,
+                                  const nsAString& aValue,
+                                  bool aDefer)
 {
   nsIDocument *ownerDoc = OwnerDoc();
   if (ownerDoc->IsLoadedAsData()) {
     // Make this a no-op rather than throwing an error to avoid
     // the error causing problems setting the attribute.
     return NS_OK;
   }
 
@@ -1824,18 +1824,19 @@ nsGenericElement::AddScriptEventListener
   bool defer = true;
   nsEventListenerManager* manager = GetEventListenerManagerForAttr(aEventName,
                                                                    &defer);
   if (!manager) {
     return NS_OK;
   }
 
   defer = defer && aDefer; // only defer if everyone agrees...
-  manager->AddScriptEventListener(aEventName, aValue, nsIProgrammingLanguage::JAVASCRIPT,
-                                  defer, !nsContentUtils::IsChromeDoc(ownerDoc));
+  manager->SetEventHandler(aEventName, aValue,
+                           nsIProgrammingLanguage::JAVASCRIPT,
+                           defer, !nsContentUtils::IsChromeDoc(ownerDoc));
   return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 
 const nsAttrName*
 nsGenericElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -205,19 +205,19 @@ public:
 
   /**
    * Add a script event listener with the given event handler name
    * (like onclick) and with the value as JS
    * @param aEventName the event listener name
    * @param aValue the JS to attach
    * @param aDefer indicates if deferred execution is allowed
    */
-  nsresult AddScriptEventListener(nsIAtom* aEventName,
-                                  const nsAString& aValue,
-                                  bool aDefer = true);
+  nsresult SetEventHandler(nsIAtom* aEventName,
+                           const nsAString& aValue,
+                           bool aDefer = true);
 
   /**
    * Do whatever needs to be done when the mouse leaves a link
    */
   nsresult LeaveLink(nsPresContext* aPresContext);
 
   static bool ShouldBlur(nsIContent *aContent);
 
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -92,17 +92,18 @@
 #include "nsSVGUtils.h"
 #include "nsTextNode.h"
 #include "nsUnicharUtils.h"
 #include "nsXBLBinding.h"
 #include "nsXBLInsertionPoint.h"
 #include "nsXBLPrototypeBinding.h"
 #include "prprf.h"
 #include "xpcpublic.h"
-
+#include "nsCSSRuleProcessor.h"
+#include "nsCSSParser.h"
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsINode::nsSlots::~nsSlots()
 {
   if (mChildNodes) {
@@ -1959,36 +1960,36 @@ nsINode::SizeOfExcludingThis(nsMallocSiz
   // The following members are not measured:
   // - mParent, mNextSibling, mPreviousSibling, mFirstChild: because they're
   //   non-owning
   return n;
 }
 
 #define EVENT(name_, id_, type_, struct_)                                    \
   NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) {            \
-    nsEventListenerManager *elm = GetListenerManager(false);              \
+    nsEventListenerManager *elm = GetListenerManager(false);                 \
     if (elm) {                                                               \
-      elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
+      elm->GetEventHandler(nsGkAtoms::on##name_, vp);                        \
     } else {                                                                 \
       *vp = JSVAL_NULL;                                                      \
     }                                                                        \
     return NS_OK;                                                            \
   }                                                                          \
   NS_IMETHODIMP nsINode::SetOn##name_(JSContext *cx, const jsval &v) {       \
-    nsEventListenerManager *elm = GetListenerManager(true);               \
+    nsEventListenerManager *elm = GetListenerManager(true);                  \
     if (!elm) {                                                              \
       return NS_ERROR_OUT_OF_MEMORY;                                         \
     }                                                                        \
                                                                              \
     JSObject *obj = GetWrapper();                                            \
     if (!obj) {                                                              \
       /* Just silently do nothing */                                         \
       return NS_OK;                                                          \
     }                                                                        \
-    return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
+    return elm->SetEventHandlerToJsval(nsGkAtoms::on##name_, cx, obj, v);    \
 }
 #define TOUCH_EVENT EVENT
 #define DOCUMENT_ONLY_EVENT EVENT
 #include "nsEventNameList.h"
 #undef DOCUMENT_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef EVENT
 
@@ -2048,8 +2049,189 @@ nsINode::Length() const
   case nsIDOMNode::COMMENT_NODE:
     MOZ_ASSERT(IsNodeOfType(eCONTENT));
     return static_cast<const nsIContent*>(this)->TextLength();
 
   default:
     return GetChildCount();
   }
 }
+
+NS_IMPL_CYCLE_COLLECTION_1(nsNodeSelectorTearoff, mNode)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSelectorTearoff)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNodeSelector)
+NS_INTERFACE_MAP_END_AGGREGATED(mNode)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSelectorTearoff)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSelectorTearoff)
+
+NS_IMETHODIMP
+nsNodeSelectorTearoff::QuerySelector(const nsAString& aSelector,
+                                     nsIDOMElement **aReturn)
+{
+  nsresult rv;
+  nsIContent* result = mNode->QuerySelector(aSelector, &rv);
+  return result ? CallQueryInterface(result, aReturn) : rv;
+}
+
+NS_IMETHODIMP
+nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
+                                        nsIDOMNodeList **aReturn)
+{
+  return mNode->QuerySelectorAll(aSelector, aReturn);
+}
+
+// NOTE: The aPresContext pointer is NOT addrefed.
+// *aSelectorList might be null even if NS_OK is returned; this
+// happens when all the selectors were pseudo-element selectors.
+static nsresult
+ParseSelectorList(nsINode* aNode,
+                  const nsAString& aSelectorString,
+                  nsCSSSelectorList** aSelectorList)
+{
+  NS_ENSURE_ARG(aNode);
+
+  nsIDocument* doc = aNode->OwnerDoc();
+  nsCSSParser parser(doc->CSSLoader());
+
+  nsCSSSelectorList* selectorList;
+  nsresult rv = parser.ParseSelectorString(aSelectorString,
+                                           doc->GetDocumentURI(),
+                                           0, // XXXbz get the line number!
+                                           &selectorList);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Filter out pseudo-element selectors from selectorList
+  nsCSSSelectorList** slot = &selectorList;
+  do {
+    nsCSSSelectorList* cur = *slot;
+    if (cur->mSelectors->IsPseudoElement()) {
+      *slot = cur->mNext;
+      cur->mNext = nullptr;
+      delete cur;
+    } else {
+      slot = &cur->mNext;
+    }
+  } while (*slot);
+  *aSelectorList = selectorList;
+
+  return NS_OK;
+}
+
+// Actually find elements matching aSelectorList (which must not be
+// null) and which are descendants of aRoot and put them in aList.  If
+// onlyFirstMatch, then stop once the first one is found.
+template<bool onlyFirstMatch, class T>
+inline static nsresult FindMatchingElements(nsINode* aRoot,
+                                            const nsAString& aSelector,
+                                            T &aList)
+{
+  nsAutoPtr<nsCSSSelectorList> selectorList;
+  nsresult rv = ParseSelectorList(aRoot, aSelector,
+                                  getter_Transfers(selectorList));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(selectorList, NS_OK);
+
+  NS_ASSERTION(selectorList->mSelectors,
+               "How can we not have any selectors?");
+
+  nsIDocument* doc = aRoot->OwnerDoc();
+  TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
+                                   doc, TreeMatchContext::eNeverMatchVisited);
+  doc->FlushPendingLinkUpdates();
+
+  // Fast-path selectors involving IDs.  We can only do this if aRoot
+  // is in the document and the document is not in quirks mode, since
+  // ID selectors are case-insensitive in quirks mode.  Also, only do
+  // this if selectorList only has one selector, because otherwise
+  // ordering the elements correctly is a pain.
+  NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
+               !aRoot->IsInDoc(),
+               "The optimization below to check ContentIsDescendantOf only for "
+               "elements depends on aRoot being either an element or a "
+               "document if it's in the document.");
+  if (aRoot->IsInDoc() &&
+      doc->GetCompatibilityMode() != eCompatibility_NavQuirks &&
+      !selectorList->mNext &&
+      selectorList->mSelectors->mIDList) {
+    nsIAtom* id = selectorList->mSelectors->mIDList->mAtom;
+    const nsSmallVoidArray* elements =
+      doc->GetAllElementsForId(nsDependentAtomString(id));
+
+    // XXXbz: Should we fall back to the tree walk if aRoot is not the
+    // document and |elements| is long, for some value of "long"?
+    if (elements) {
+      for (int32_t i = 0; i < elements->Count(); ++i) {
+        Element *element = static_cast<Element*>(elements->ElementAt(i));
+        if (!aRoot->IsElement() ||
+            (element != aRoot &&
+             nsContentUtils::ContentIsDescendantOf(element, aRoot))) {
+          // We have an element with the right id and it's a strict descendant
+          // of aRoot.  Make sure it really matches the selector.
+          if (nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
+                                                      selectorList)) {
+            aList.AppendElement(element);
+            if (onlyFirstMatch) {
+              return NS_OK;
+            }
+          }
+        }
+      }
+    }
+
+    // No elements with this id, or none of them are our descendants,
+    // or none of them match.  We're done here.
+    return NS_OK;
+  }
+
+  for (nsIContent* cur = aRoot->GetFirstChild();
+       cur;
+       cur = cur->GetNextNode(aRoot)) {
+    if (cur->IsElement() &&
+        nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
+                                                matchingContext,
+                                                selectorList)) {
+      aList.AppendElement(cur->AsElement());
+      if (onlyFirstMatch) {
+        return NS_OK;
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+struct ElementHolder {
+  ElementHolder() : mElement(nullptr) {}
+  void AppendElement(Element* aElement) {
+    NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
+    mElement = aElement;
+  }
+  Element* mElement;
+};
+
+nsIContent*
+nsINode::QuerySelector(const nsAString& aSelector,
+                       nsresult *aResult)
+{
+  NS_PRECONDITION(aResult, "Null out param?");
+
+  ElementHolder holder;
+  *aResult = FindMatchingElements<true>(this, aSelector, holder);
+
+  return holder.mElement;
+}
+
+/* static */
+nsresult
+nsINode::QuerySelectorAll(const nsAString& aSelector,
+                          nsIDOMNodeList **aReturn)
+{
+  NS_PRECONDITION(aReturn, "Null out param?");
+
+  nsSimpleContentList* contentList = new nsSimpleContentList(this);
+  NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
+  NS_ADDREF(*aReturn = contentList);
+
+  return FindMatchingElements<false>(this, aSelector, *contentList);
+}
+
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -2268,19 +2268,19 @@ nsObjectLoadingContent::LoadFallback(Fal
 
   //
   // Fixup mFallbackType
   //
   nsCOMPtr<nsIContent> thisContent =
   do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
 
-  if (!thisContent->IsHTML()) {
-    // Don't let custom fallback handlers run outside HTML
-    LOG(("OBJLC [%p]: Non-HTML content, forcing eFallbackAlternate", this));
+  if (!thisContent->IsHTML() || mContentType.IsEmpty()) {
+    // Don't let custom fallback handlers run outside HTML, tags without a
+    // determined type should always just be alternate content
     aType = eFallbackAlternate;
   }
 
   /// XXX(johns): This block is just mimicing legacy behavior, not any spec
   // Check if we have any significant content (excluding param tags) OR a
   // param named 'pluginUrl'
   bool hasAlternateContent = false;
   bool hasPluginUrl = false;
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1465,17 +1465,17 @@ nsXMLHttpRequest::GetAllResponseHeaders(
     AppendASCIItoUTF16(value, aResponseHeaders);
     if (NS_SUCCEEDED(mChannel->GetContentCharset(value)) && !value.IsEmpty()) {
       aResponseHeaders.AppendLiteral(";charset=");
       AppendASCIItoUTF16(value, aResponseHeaders);
     }
     aResponseHeaders.AppendLiteral("\r\n");
   }
 
-  PRInt32 length;
+  int32_t length;
   if (NS_SUCCEEDED(mChannel->GetContentLength(&length))) {
     aResponseHeaders.AppendLiteral("Content-Length: ");
     aResponseHeaders.AppendInt(length);
     aResponseHeaders.AppendLiteral("\r\n");
   }
 }
 
 NS_IMETHODIMP
@@ -1526,17 +1526,17 @@ nsXMLHttpRequest::GetResponseHeader(cons
           !value.IsEmpty()) {
         _retval.Append(";charset=");
         _retval.Append(value);
       }
     }
 
     // Content Length:
     else if (header.LowerCaseEqualsASCII("content-length")) {
-      PRInt32 length;
+      int32_t length;
       if (NS_SUCCEEDED(mChannel->GetContentLength(&length))) {
         _retval.AppendInt(length);
       }
     }
 
     return;
   }
 
--- a/content/canvas/src/CanvasUtils.cpp
+++ b/content/canvas/src/CanvasUtils.cpp
@@ -49,19 +49,21 @@ DoDrawImageSecurityCheck(nsHTMLCanvasEle
         aCanvasElement->SetWriteOnly();
         return;
     }
 
     // No need to do a security check if the image used CORS for the load
     if (CORSUsed)
         return;
 
+    // Ignore document.domain in this check.
     bool subsumes;
     nsresult rv =
-        aCanvasElement->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
+        aCanvasElement->NodePrincipal()->SubsumesIgnoringDomain(aPrincipal,
+                                                                &subsumes);
 
     if (NS_SUCCEEDED(rv) && subsumes) {
         // This canvas has access to that image anyway
         return;
     }
 
     aCanvasElement->SetWriteOnly();
 }
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -52,16 +52,18 @@ MOCHITEST_FILES = \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
 	test_bug764125.html \
 	test_drawImage_edge_cases.html \
+	test_drawImage_document_domain.html \
+	file_drawImage_document_domain.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
 MOCHITEST_FILES += test_2d.composite.uncovered.image.destination-atop.html
 endif
 
 # xor and lighter aren't well handled by cairo; they mostly work, but we don't want
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/file_drawImage_document_domain.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+  <canvas id="c" width="1" height="1"></canvas>
+  <img id="img" src="image_green-1x1.png">
+<script>
+  window.onmessage = function(ev) {
+    if (ev.data != "start") {
+      parent.postMessage({ msg: "unknown_message", data: ev.data }, "*");
+      return;
+    }
+
+    // Set document.domain to itself, so we trigger the
+    // "set effective script origin" cases.
+    document.domain = document.domain
+    var ctx = document.getElementById("c").getContext("2d");
+    ctx.drawImage(document.getElementById("img"), 0, 0);
+    try {
+      var data = ctx.getImageData(0, 0, 1, 1).data;
+      parent.postMessage(
+        {
+          msg: "color",
+          data: "rgba(" + data[0] + ", " + data[1] + ", " + data[2] + ", " + data[3]/255 + ")"
+        },
+        "*");
+    } catch (e) {
+      parent.postMessage({ msg: "exception", data: e.toString() }, "*");
+    }
+
+    parent.postMessage({ msg: "done" }, "*");
+  }
+</script>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_drawImage_document_domain.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567511
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 567511</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567511">Mozilla Bug 567511</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe src="file_drawImage_document_domain.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 567511 **/
+
+SimpleTest.waitForExplicitFinish();
+
+window.onmessage = function(ev) {
+  if (ev.data.msg == "done") {
+    SimpleTest.finish();
+  } else if (ev.data.msg == "exception") {
+    ok(false, ev.data.data);
+  } else if (ev.data.msg == "color") {
+    is(ev.data.data, "rgba(0, 255, 0, 1)", "Should get correct color");
+  } else if (ev.data.msg == "unknown_message") {
+    ok(false, "Unknown message to child: " + ev.data.data);
+  } else {
+    ok(false, "Unknown message from child: " + ev.data.msg);
+  }
+}
+
+function doTest() {
+  frames[0].postMessage("start", "*");
+}
+
+addLoadEvent(doTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -46,16 +46,40 @@
  * Event names that are not exposed as IDL attributes at all should be
  * enclosed in NON_IDL_EVENT.  If NON_IDL_EVENT is not defined, it
  * will be defined to the empty string.
  *
  * If you change which macros event names are enclosed in, please
  * update the tests for bug 689564 and bug 659350 as needed.
  */
 
+#ifdef ID_TO_EVENT
+#ifdef EVENT
+#error "Don't define EVENT"
+#endif /* EVENT */
+#ifdef WINDOW_ONLY_EVENT
+#error "Don't define WINDOW_ONLY_EVENT"
+#endif /* WINDOW_ONLY_EVENT */
+#ifdef TOUCH_EVENT
+#error "Don't define TOUCH_EVENT"
+#endif /* TOUCH_EVENT */
+#ifdef DOCUMENT_ONLY_EVENT
+#error "Don't define DOCUMENT_ONLY_EVENT"
+#endif /* DOCUMENT_ONLY_EVENT */
+#ifdef NON_IDL_EVENT
+#error "Don't define NON_IDL_EVENT"
+#endif /* NON_IDL_EVENT */
+
+#define EVENT ID_TO_EVENT
+#define WINDOW_ONLY_EVENT ID_TO_EVENT
+#define TOUCH_EVENT ID_TO_EVENT
+#define DOCUMENT_ONLY_EVENT ID_TO_EVENT
+#define NON_IDL_EVENT ID_TO_EVENT
+#endif
+
 #ifdef DEFINED_FORWARDED_EVENT
 #error "Don't define DEFINED_FORWARDED_EVENT"
 #endif /* DEFINED_FORWARDED_EVENT */
 
 #ifndef FORWARDED_EVENT
 #define FORWARDED_EVENT EVENT
 #define DEFINED_FORWARDED_EVENT
 #endif /* FORWARDED_EVENT */
@@ -630,41 +654,54 @@ NON_IDL_EVENT(SVGScroll,
               NS_SVG_SCROLL,
               EventNameType_None,
               NS_SVG_EVENT)
 
 NON_IDL_EVENT(SVGZoom,
               NS_SVG_ZOOM,
               EventNameType_None,
               NS_SVGZOOM_EVENT)
+
+// Only map the ID to the real event name when ID_TO_EVENT is defined.
+#ifndef ID_TO_EVENT
 // This is a bit hackish, but SVG's event names are weird.
 NON_IDL_EVENT(zoom,
               NS_SVG_ZOOM,
               EventNameType_SVGSVG,
               NS_EVENT_NULL)
+#endif
+// Only map the ID to the real event name when ID_TO_EVENT is defined.
+#ifndef ID_TO_EVENT
 NON_IDL_EVENT(begin,
               NS_SMIL_BEGIN,
               EventNameType_SMIL,
               NS_EVENT_NULL)
+#endif
 NON_IDL_EVENT(beginEvent,
               NS_SMIL_BEGIN,
               EventNameType_None,
               NS_SMIL_TIME_EVENT)
+// Only map the ID to the real event name when ID_TO_EVENT is defined.
+#ifndef ID_TO_EVENT
 NON_IDL_EVENT(end,
               NS_SMIL_END,
               EventNameType_SMIL,
               NS_EVENT_NULL)
+#endif
 NON_IDL_EVENT(endEvent,
               NS_SMIL_END,
               EventNameType_None,
               NS_SMIL_TIME_EVENT)
+// Only map the ID to the real event name when ID_TO_EVENT is defined.
+#ifndef ID_TO_EVENT
 NON_IDL_EVENT(repeat,
               NS_SMIL_REPEAT,
               EventNameType_SMIL,
               NS_EVENT_NULL)
+#endif
 NON_IDL_EVENT(repeatEvent,
               NS_SMIL_REPEAT,
               EventNameType_None,
               NS_SMIL_TIME_EVENT)
 
 NON_IDL_EVENT(MozAudioAvailable,
               NS_MOZAUDIOAVAILABLE,
               EventNameType_None,
@@ -776,8 +813,16 @@ NON_IDL_EVENT(animationiteration,
 #undef DOCUMENT_ONLY_EVENT
 #endif /* DEFINED_DOCUMENT_ONLY_EVENT */
 
 #ifdef DEFINED_NON_IDL_EVENT
 #undef DEFINED_NON_IDL_EVENT
 #undef NON_IDL_EVENT
 #endif /* DEFINED_NON_IDL_EVENT */
 
+#ifdef ID_TO_EVENT
+#undef EVENT
+#undef WINDOW_ONLY_EVENT
+#undef TOUCH_EVENT
+#undef DOCUMENT_ONLY_EVENT
+#undef NON_IDL_EVENT
+#endif /* ID_TO_EVENT */
+
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -30,81 +30,16 @@
 #include "nsJSUtils.h"
 #include "DictionaryHelpers.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsDOMClassInfoID.h"
 
 using namespace mozilla;
 
-static const char* const sEventNames[] = {
-  "mousedown", "mouseup", "click", "dblclick", "mouseenter", "mouseleave", "mouseover",
-  "mouseout", "MozMouseHittest", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
-  "focus", "blur", "load", "popstate", "beforescriptexecute",
-  "afterscriptexecute", "beforeunload", "unload",
-  "hashchange", "readystatechange", "abort", "error",
-  "submit", "reset", "change", "select", "input", "invalid", "text",
-  "compositionstart", "compositionend", "compositionupdate",
-  "popupshowing", "popupshown",
-  "popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
-  "dragenter", "dragover", "dragexit", "dragdrop", "draggesture",
-  "drag", "dragend", "dragstart", "dragleave", "drop", "resize",
-  "scroll", "overflow", "underflow", "overflowchanged",
-  "DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved", 
-  "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
-  "DOMAttrModified", "DOMCharacterDataModified",
-  "DOMActivate", "DOMFocusIn", "DOMFocusOut",
-  "pageshow", "pagehide", "DOMMouseScroll", "MozMousePixelScroll", "wheel",
-  "offline", "online", "copy", "cut", "paste", "open", "message", "show",
-  "SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
-  "SVGZoom",
-  "beginEvent", "endEvent", "repeatEvent",
-#ifdef MOZ_MEDIA
-  "loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
-  "loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
-  "canplaythrough", "seeking", "seeked", "timeupdate", "ended", "ratechange",
-  "durationchange", "volumechange", "MozAudioAvailable",
-#endif // MOZ_MEDIA
-  "MozAfterPaint",
-  "MozBeforeResize",
-  "mozfullscreenchange",
-  "mozfullscreenerror",
-  "mozpointerlockchange",
-  "mozpointerlockerror",
-  "MozSwipeGesture",
-  "MozMagnifyGestureStart",
-  "MozMagnifyGestureUpdate",
-  "MozMagnifyGesture",
-  "MozRotateGestureStart",
-  "MozRotateGestureUpdate",
-  "MozRotateGesture",
-  "MozTapGesture",
-  "MozPressTapGesture",
-  "MozEdgeUIGesture",
-  "MozTouchDown",
-  "MozTouchMove",
-  "MozTouchUp",
-  "touchstart",
-  "touchend",
-  "touchmove",
-  "touchcancel",
-  "touchenter",
-  "touchleave",
-  "MozScrolledAreaChanged",
-  "transitionend",
-  "animationstart",
-  "animationend",
-  "animationiteration",
-  "devicemotion",
-  "deviceorientation",
-  "deviceproximity",
-  "userproximity",
-  "devicelight"
-};
-
 static char *sPopupAllowedEvents;
 
 
 nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
 {
   mPrivateDataDuplicated = false;
 
   if (aEvent) {
@@ -1231,310 +1166,20 @@ nsDOMEvent::GetClientCoords(nsPresContex
 }
 
 // To be called ONLY by nsDOMEvent::GetType (which has the additional
 // logic for handling user-defined events).
 // static
 const char* nsDOMEvent::GetEventName(uint32_t aEventType)
 {
   switch(aEventType) {
-  case NS_MOUSE_BUTTON_DOWN:
-    return sEventNames[eDOMEvents_mousedown];
-  case NS_MOUSE_BUTTON_UP:
-    return sEventNames[eDOMEvents_mouseup];
-  case NS_MOUSE_CLICK:
-    return sEventNames[eDOMEvents_click];
-  case NS_MOUSE_DOUBLECLICK:
-    return sEventNames[eDOMEvents_dblclick];
-  case NS_MOUSEENTER:
-    return sEventNames[eDOMEvents_mouseenter];
-  case NS_MOUSELEAVE:
-    return sEventNames[eDOMEvents_mouseleave];
-  case NS_MOUSE_ENTER_SYNTH:
-    return sEventNames[eDOMEvents_mouseover];
-  case NS_MOUSE_EXIT_SYNTH:
-    return sEventNames[eDOMEvents_mouseout];
-  case NS_MOUSE_MOZHITTEST:
-    return sEventNames[eDOMEvents_MozMouseHittest];
-  case NS_MOUSE_MOVE:
-    return sEventNames[eDOMEvents_mousemove];
-  case NS_KEY_UP:
-    return sEventNames[eDOMEvents_keyup];
-  case NS_KEY_DOWN:
-    return sEventNames[eDOMEvents_keydown];
-  case NS_KEY_PRESS:
-    return sEventNames[eDOMEvents_keypress];
-  case NS_COMPOSITION_START:
-    return sEventNames[eDOMEvents_compositionstart];
-  case NS_COMPOSITION_UPDATE:
-    return sEventNames[eDOMEvents_compositionupdate];
-  case NS_COMPOSITION_END:
-    return sEventNames[eDOMEvents_compositionend];
-  case NS_FOCUS_CONTENT:
-    return sEventNames[eDOMEvents_focus];
-  case NS_BLUR_CONTENT:
-    return sEventNames[eDOMEvents_blur];
-  case NS_XUL_CLOSE:
-    return sEventNames[eDOMEvents_close];
-  case NS_LOAD:
-    return sEventNames[eDOMEvents_load];
-  case NS_POPSTATE:
-    return sEventNames[eDOMEvents_popstate];
-  case NS_BEFORE_SCRIPT_EXECUTE:
-    return sEventNames[eDOMEvents_beforescriptexecute];
-  case NS_AFTER_SCRIPT_EXECUTE:
-    return sEventNames[eDOMEvents_afterscriptexecute];
-  case NS_BEFORE_PAGE_UNLOAD:
-    return sEventNames[eDOMEvents_beforeunload];
-  case NS_PAGE_UNLOAD:
-    return sEventNames[eDOMEvents_unload];
-  case NS_HASHCHANGE:
-    return sEventNames[eDOMEvents_hashchange];
-  case NS_READYSTATECHANGE:
-    return sEventNames[eDOMEvents_readystatechange];
-  case NS_IMAGE_ABORT:
-    return sEventNames[eDOMEvents_abort];
-  case NS_LOAD_ERROR:
-    return sEventNames[eDOMEvents_error];
-  case NS_FORM_SUBMIT:
-    return sEventNames[eDOMEvents_submit];
-  case NS_FORM_RESET:
-    return sEventNames[eDOMEvents_reset];
-  case NS_FORM_CHANGE:
-    return sEventNames[eDOMEvents_change];
-  case NS_FORM_SELECTED:
-    return sEventNames[eDOMEvents_select];
-  case NS_FORM_INPUT:
-    return sEventNames[eDOMEvents_input];
-  case NS_FORM_INVALID:
-    return sEventNames[eDOMEvents_invalid];
-  case NS_RESIZE_EVENT:
-    return sEventNames[eDOMEvents_resize];
-  case NS_SCROLL_EVENT:
-    return sEventNames[eDOMEvents_scroll];
-  case NS_TEXT_TEXT:
-    return sEventNames[eDOMEvents_text];
-  case NS_XUL_POPUP_SHOWING:
-    return sEventNames[eDOMEvents_popupShowing];
-  case NS_XUL_POPUP_SHOWN:
-    return sEventNames[eDOMEvents_popupShown];
-  case NS_XUL_POPUP_HIDING:
-    return sEventNames[eDOMEvents_popupHiding];
-  case NS_XUL_POPUP_HIDDEN:
-    return sEventNames[eDOMEvents_popupHidden];
-  case NS_XUL_COMMAND:
-    return sEventNames[eDOMEvents_command];
-  case NS_XUL_BROADCAST:
-    return sEventNames[eDOMEvents_broadcast];
-  case NS_XUL_COMMAND_UPDATE:
-    return sEventNames[eDOMEvents_commandupdate];
-  case NS_DRAGDROP_ENTER:
-    return sEventNames[eDOMEvents_dragenter];
-  case NS_DRAGDROP_OVER_SYNTH:
-    return sEventNames[eDOMEvents_dragover];
-  case NS_DRAGDROP_EXIT_SYNTH:
-    return sEventNames[eDOMEvents_dragexit];
-  case NS_DRAGDROP_DRAGDROP:
-    return sEventNames[eDOMEvents_dragdrop];
-  case NS_DRAGDROP_GESTURE:
-    return sEventNames[eDOMEvents_draggesture];
-  case NS_DRAGDROP_DRAG:
-    return sEventNames[eDOMEvents_drag];
-  case NS_DRAGDROP_END:
-    return sEventNames[eDOMEvents_dragend];
-  case NS_DRAGDROP_START:
-    return sEventNames[eDOMEvents_dragstart];
-  case NS_DRAGDROP_LEAVE_SYNTH:
-    return sEventNames[eDOMEvents_dragleave];
-  case NS_DRAGDROP_DROP:
-    return sEventNames[eDOMEvents_drop];
-  case NS_SCROLLPORT_OVERFLOW:
-    return sEventNames[eDOMEvents_overflow];
-  case NS_SCROLLPORT_UNDERFLOW:
-    return sEventNames[eDOMEvents_underflow];
-  case NS_SCROLLPORT_OVERFLOWCHANGED:
-    return sEventNames[eDOMEvents_overflowchanged];
-  case NS_MUTATION_SUBTREEMODIFIED:
-    return sEventNames[eDOMEvents_subtreemodified];
-  case NS_MUTATION_NODEINSERTED:
-    return sEventNames[eDOMEvents_nodeinserted];
-  case NS_MUTATION_NODEREMOVED:
-    return sEventNames[eDOMEvents_noderemoved];
-  case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
-    return sEventNames[eDOMEvents_noderemovedfromdocument];
-  case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
-    return sEventNames[eDOMEvents_nodeinsertedintodocument];
-  case NS_MUTATION_ATTRMODIFIED:
-    return sEventNames[eDOMEvents_attrmodified];
-  case NS_MUTATION_CHARACTERDATAMODIFIED:
-    return sEventNames[eDOMEvents_characterdatamodified];
-  case NS_CONTEXTMENU:
-    return sEventNames[eDOMEvents_contextmenu];
-  case NS_UI_ACTIVATE:
-    return sEventNames[eDOMEvents_DOMActivate];
-  case NS_UI_FOCUSIN:
-    return sEventNames[eDOMEvents_DOMFocusIn];
-  case NS_UI_FOCUSOUT:
-    return sEventNames[eDOMEvents_DOMFocusOut];
-  case NS_PAGE_SHOW:
-    return sEventNames[eDOMEvents_pageshow];
-  case NS_PAGE_HIDE:
-    return sEventNames[eDOMEvents_pagehide];
-  case NS_MOUSE_SCROLL:
-    return sEventNames[eDOMEvents_DOMMouseScroll];
-  case NS_MOUSE_PIXEL_SCROLL:
-    return sEventNames[eDOMEvents_MozMousePixelScroll];
-  case NS_WHEEL_WHEEL:
-    return sEventNames[eDOMEvents_wheel];
-  case NS_OFFLINE:
-    return sEventNames[eDOMEvents_offline];
-  case NS_ONLINE:
-    return sEventNames[eDOMEvents_online];
-  case NS_COPY:
-    return sEventNames[eDOMEvents_copy];
-  case NS_CUT:
-    return sEventNames[eDOMEvents_cut];
-  case NS_PASTE:
-    return sEventNames[eDOMEvents_paste];
-  case NS_OPEN:
-    return sEventNames[eDOMEvents_open];
-  case NS_MESSAGE:
-    return sEventNames[eDOMEvents_message];
-  case NS_SHOW_EVENT:
-    return sEventNames[eDOMEvents_show];
-  case NS_SVG_LOAD:
-    return sEventNames[eDOMEvents_SVGLoad];
-  case NS_SVG_UNLOAD:
-    return sEventNames[eDOMEvents_SVGUnload];
-  case NS_SVG_ABORT:
-    return sEventNames[eDOMEvents_SVGAbort];
-  case NS_SVG_ERROR:
-    return sEventNames[eDOMEvents_SVGError];
-  case NS_SVG_RESIZE:
-    return sEventNames[eDOMEvents_SVGResize];
-  case NS_SVG_SCROLL:
-    return sEventNames[eDOMEvents_SVGScroll];
-  case NS_SVG_ZOOM:
-    return sEventNames[eDOMEvents_SVGZoom];
-  case NS_TOUCH_START:
-    return sEventNames[eDOMEvents_touchstart];
-  case NS_TOUCH_MOVE:
-    return sEventNames[eDOMEvents_touchmove];
-  case NS_TOUCH_END:
-    return sEventNames[eDOMEvents_touchend];
-  case NS_TOUCH_ENTER:
-    return sEventNames[eDOMEvents_touchenter];
-  case NS_TOUCH_LEAVE:
-    return sEventNames[eDOMEvents_touchleave];
-  case NS_TOUCH_CANCEL:
-    return sEventNames[eDOMEvents_touchcancel];
-  case NS_SMIL_BEGIN:
-    return sEventNames[eDOMEvents_beginEvent];
-  case NS_SMIL_END:
-    return sEventNames[eDOMEvents_endEvent];
-  case NS_SMIL_REPEAT:
-    return sEventNames[eDOMEvents_repeatEvent];
-#ifdef MOZ_MEDIA
-  case NS_LOADSTART:
-    return sEventNames[eDOMEvents_loadstart];
-  case NS_PROGRESS:
-    return sEventNames[eDOMEvents_progress];
-  case NS_SUSPEND:
-    return sEventNames[eDOMEvents_suspend];
-  case NS_EMPTIED:
-    return sEventNames[eDOMEvents_emptied];
-  case NS_STALLED:
-    return sEventNames[eDOMEvents_stalled];
-  case NS_PLAY:
-    return sEventNames[eDOMEvents_play];
-  case NS_PAUSE:
-    return sEventNames[eDOMEvents_pause];
-  case NS_LOADEDMETADATA:
-    return sEventNames[eDOMEvents_loadedmetadata];
-  case NS_LOADEDDATA:
-    return sEventNames[eDOMEvents_loadeddata];
-  case NS_WAITING:
-    return sEventNames[eDOMEvents_waiting];
-  case NS_PLAYING:
-    return sEventNames[eDOMEvents_playing];
-  case NS_CANPLAY:
-    return sEventNames[eDOMEvents_canplay];
-  case NS_CANPLAYTHROUGH:
-    return sEventNames[eDOMEvents_canplaythrough];
-  case NS_SEEKING:
-    return sEventNames[eDOMEvents_seeking];
-  case NS_SEEKED:
-    return sEventNames[eDOMEvents_seeked];
-  case NS_TIMEUPDATE:
-    return sEventNames[eDOMEvents_timeupdate];
-  case NS_ENDED:
-    return sEventNames[eDOMEvents_ended];
-  case NS_RATECHANGE:
-    return sEventNames[eDOMEvents_ratechange];
-  case NS_DURATIONCHANGE:
-    return sEventNames[eDOMEvents_durationchange];
-  case NS_VOLUMECHANGE:
-    return sEventNames[eDOMEvents_volumechange];
-  case NS_MOZAUDIOAVAILABLE:
-    return sEventNames[eDOMEvents_mozaudioavailable];
-#endif
-  case NS_AFTERPAINT:
-    return sEventNames[eDOMEvents_afterpaint];
-  case NS_BEFORERESIZE_EVENT:
-    return sEventNames[eDOMEvents_beforeresize];
-  case NS_SIMPLE_GESTURE_SWIPE:
-    return sEventNames[eDOMEvents_MozSwipeGesture];
-  case NS_SIMPLE_GESTURE_MAGNIFY_START:
-    return sEventNames[eDOMEvents_MozMagnifyGestureStart];
-  case NS_SIMPLE_GESTURE_MAGNIFY_UPDATE:
-    return sEventNames[eDOMEvents_MozMagnifyGestureUpdate];
-  case NS_SIMPLE_GESTURE_MAGNIFY:
-    return sEventNames[eDOMEvents_MozMagnifyGesture];
-  case NS_SIMPLE_GESTURE_ROTATE_START:
-    return sEventNames[eDOMEvents_MozRotateGestureStart];
-  case NS_SIMPLE_GESTURE_ROTATE_UPDATE:
-    return sEventNames[eDOMEvents_MozRotateGestureUpdate];
-  case NS_SIMPLE_GESTURE_ROTATE:
-    return sEventNames[eDOMEvents_MozRotateGesture];
-  case NS_SIMPLE_GESTURE_TAP:
-    return sEventNames[eDOMEvents_MozTapGesture];
-  case NS_SIMPLE_GESTURE_PRESSTAP:
-    return sEventNames[eDOMEvents_MozPressTapGesture];
-  case NS_SIMPLE_GESTURE_EDGEUI:
-    return sEventNames[eDOMEvents_MozEdgeUIGesture];
-  case NS_MOZTOUCH_DOWN:
-    return sEventNames[eDOMEvents_MozTouchDown];
-  case NS_MOZTOUCH_MOVE:
-    return sEventNames[eDOMEvents_MozTouchMove];
-  case NS_MOZTOUCH_UP:
-    return sEventNames[eDOMEvents_MozTouchUp];
-  case NS_SCROLLEDAREACHANGED:
-    return sEventNames[eDOMEvents_MozScrolledAreaChanged];
-  case NS_TRANSITION_END:
-    return sEventNames[eDOMEvents_transitionend];
-  case NS_ANIMATION_START:
-    return sEventNames[eDOMEvents_animationstart];
-  case NS_ANIMATION_END:
-    return sEventNames[eDOMEvents_animationend];
-  case NS_ANIMATION_ITERATION:
-    return sEventNames[eDOMEvents_animationiteration];
-  case NS_DEVICE_MOTION:
-    return sEventNames[eDOMEvents_devicemotion];
-  case NS_DEVICE_ORIENTATION:
-    return sEventNames[eDOMEvents_deviceorientation];
-  case NS_DEVICE_PROXIMITY:
-    return sEventNames[eDOMEvents_deviceproximity];
-  case NS_USER_PROXIMITY:
-    return sEventNames[eDOMEvents_userproximity];
-  case NS_DEVICE_LIGHT:
-    return sEventNames[eDOMEvents_devicelight];
-  case NS_FULLSCREENCHANGE:
-    return sEventNames[eDOMEvents_mozfullscreenchange];
-  case NS_FULLSCREENERROR:
-    return sEventNames[eDOMEvents_mozfullscreenerror];
+#define ID_TO_EVENT(name_, _id, _type, _struct) \
+  case _id: return #name_;
+#include "nsEventNameList.h"
+#undef ID_TO_EVENT
   default:
     break;
   }
   // XXXldb We can hit this case for nsEvent objects that we didn't
   // create and that are not user defined events since this function and
   // SetEventType are incomplete.  (But fixing that requires fixing the
   // arrays in nsEventListenerManager too, since the events for which
   // this is a problem generally *are* created by nsDOMEvent.)
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -22,170 +22,16 @@ class nsPresContext;
 struct JSContext;
 struct JSObject;
  
 class nsDOMEvent : public nsIDOMEvent,
                    public nsIJSNativeInitializer
 {
 public:
 
-  // Note: this enum must be kept in sync with sEventNames in nsDOMEvent.cpp
-  enum nsDOMEvents {
-    eDOMEvents_mousedown=0,
-    eDOMEvents_mouseup,
-    eDOMEvents_click,
-    eDOMEvents_dblclick,
-    eDOMEvents_mouseenter,
-    eDOMEvents_mouseleave,
-    eDOMEvents_mouseover,
-    eDOMEvents_mouseout,
-    eDOMEvents_MozMouseHittest,
-    eDOMEvents_mousemove,
-    eDOMEvents_contextmenu,
-    eDOMEvents_keydown,
-    eDOMEvents_keyup,
-    eDOMEvents_keypress,
-    eDOMEvents_focus,
-    eDOMEvents_blur,
-    eDOMEvents_load,
-    eDOMEvents_popstate,
-    eDOMEvents_beforescriptexecute,
-    eDOMEvents_afterscriptexecute,
-    eDOMEvents_beforeunload,
-    eDOMEvents_unload,
-    eDOMEvents_hashchange,
-    eDOMEvents_readystatechange,
-    eDOMEvents_abort,
-    eDOMEvents_error,
-    eDOMEvents_submit,
-    eDOMEvents_reset,
-    eDOMEvents_change,
-    eDOMEvents_select,
-    eDOMEvents_input,
-    eDOMEvents_invalid,
-    eDOMEvents_text,
-    eDOMEvents_compositionstart,
-    eDOMEvents_compositionend,
-    eDOMEvents_compositionupdate,
-    eDOMEvents_popupShowing,
-    eDOMEvents_popupShown,
-    eDOMEvents_popupHiding,
-    eDOMEvents_popupHidden,
-    eDOMEvents_close,
-    eDOMEvents_command,
-    eDOMEvents_broadcast,
-    eDOMEvents_commandupdate,
-    eDOMEvents_dragenter,
-    eDOMEvents_dragover,
-    eDOMEvents_dragexit,
-    eDOMEvents_dragdrop,
-    eDOMEvents_draggesture,
-    eDOMEvents_drag,
-    eDOMEvents_dragend,
-    eDOMEvents_dragstart,
-    eDOMEvents_dragleave,
-    eDOMEvents_drop,
-    eDOMEvents_resize,
-    eDOMEvents_scroll,
-    eDOMEvents_overflow,
-    eDOMEvents_underflow,
-    eDOMEvents_overflowchanged,
-    eDOMEvents_subtreemodified,
-    eDOMEvents_nodeinserted,
-    eDOMEvents_noderemoved,
-    eDOMEvents_noderemovedfromdocument,
-    eDOMEvents_nodeinsertedintodocument,
-    eDOMEvents_attrmodified,
-    eDOMEvents_characterdatamodified,
-    eDOMEvents_DOMActivate,
-    eDOMEvents_DOMFocusIn,
-    eDOMEvents_DOMFocusOut,
-    eDOMEvents_pageshow,
-    eDOMEvents_pagehide,
-    eDOMEvents_DOMMouseScroll,
-    eDOMEvents_MozMousePixelScroll,
-    eDOMEvents_wheel,
-    eDOMEvents_offline,
-    eDOMEvents_online,
-    eDOMEvents_copy,
-    eDOMEvents_cut,
-    eDOMEvents_paste,
-    eDOMEvents_open,
-    eDOMEvents_message,
-    eDOMEvents_show,
-    eDOMEvents_SVGLoad,
-    eDOMEvents_SVGUnload,
-    eDOMEvents_SVGAbort,
-    eDOMEvents_SVGError,
-    eDOMEvents_SVGResize,
-    eDOMEvents_SVGScroll,
-    eDOMEvents_SVGZoom,
-    eDOMEvents_beginEvent,
-    eDOMEvents_endEvent,
-    eDOMEvents_repeatEvent,
-#ifdef MOZ_MEDIA
-    eDOMEvents_loadstart,
-    eDOMEvents_progress,
-    eDOMEvents_suspend,
-    eDOMEvents_emptied,
-    eDOMEvents_stalled,
-    eDOMEvents_play,
-    eDOMEvents_pause,
-    eDOMEvents_loadedmetadata,
-    eDOMEvents_loadeddata,
-    eDOMEvents_waiting,
-    eDOMEvents_playing,
-    eDOMEvents_canplay,
-    eDOMEvents_canplaythrough,
-    eDOMEvents_seeking,
-    eDOMEvents_seeked,
-    eDOMEvents_timeupdate,
-    eDOMEvents_ended,
-    eDOMEvents_ratechange,
-    eDOMEvents_durationchange,
-    eDOMEvents_volumechange,
-    eDOMEvents_mozaudioavailable,
-#endif
-    eDOMEvents_afterpaint,
-    eDOMEvents_beforeresize,
-    eDOMEvents_mozfullscreenchange,
-    eDOMEvents_mozfullscreenerror,
-    eDOMEvents_mozpointerlockchange,
-    eDOMEvents_mozpointerlockerror,
-    eDOMEvents_MozSwipeGesture,
-    eDOMEvents_MozMagnifyGestureStart,
-    eDOMEvents_MozMagnifyGestureUpdate,
-    eDOMEvents_MozMagnifyGesture,
-    eDOMEvents_MozRotateGestureStart,
-    eDOMEvents_MozRotateGestureUpdate,
-    eDOMEvents_MozRotateGesture,
-    eDOMEvents_MozTapGesture,
-    eDOMEvents_MozPressTapGesture,
-    eDOMEvents_MozEdgeUIGesture,
-    eDOMEvents_MozTouchDown,
-    eDOMEvents_MozTouchMove,
-    eDOMEvents_MozTouchUp,
-    eDOMEvents_touchstart,
-    eDOMEvents_touchend,
-    eDOMEvents_touchmove,
-    eDOMEvents_touchcancel,
-    eDOMEvents_touchenter,
-    eDOMEvents_touchleave,
-    eDOMEvents_MozScrolledAreaChanged,
-    eDOMEvents_transitionend,
-    eDOMEvents_animationstart,
-    eDOMEvents_animationend,
-    eDOMEvents_animationiteration,
-    eDOMEvents_devicemotion,
-    eDOMEvents_deviceorientation,
-    eDOMEvents_deviceproximity,
-    eDOMEvents_userproximity,
-    eDOMEvents_devicelight
-  };
-
   nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent);
   virtual ~nsDOMEvent();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMEvent, nsIDOMEvent)
 
   // nsIDOMEvent Interface
   NS_DECL_NSIDOMEVENT
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -450,18 +450,18 @@ nsEventListenerManager::RemoveEventListe
                                                   int32_t aFlags)
 {
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
   uint32_t type = nsContentUtils::GetEventId(atom);
   RemoveEventListener(aListener, type, atom, aFlags);
 }
 
 nsListenerStruct*
-nsEventListenerManager::FindJSEventListener(uint32_t aEventType,
-                                            nsIAtom* aTypeAtom)
+nsEventListenerManager::FindEventHandler(uint32_t aEventType,
+                                         nsIAtom* aTypeAtom)
 {
   // Run through the listeners for this type and see if a script
   // listener is registered
   nsListenerStruct *ls;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     ls = &mListeners.ElementAt(i);
     if (EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom) &&
@@ -469,38 +469,38 @@ nsEventListenerManager::FindJSEventListe
     {
       return ls;
     }
   }
   return nullptr;
 }
 
 nsresult
-nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
-                                           JSObject* aScopeObject,
-                                           nsIAtom* aName,
-                                           JSObject *aHandler,
-                                           bool aPermitUntrustedEvents,
-                                           nsListenerStruct **aListenerStruct)
+nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
+                                                JSObject* aScopeObject,
+                                                nsIAtom* aName,
+                                                JSObject *aHandler,
+                                                bool aPermitUntrustedEvents,
+                                                nsListenerStruct **aListenerStruct)
 {
   nsresult rv = NS_OK;
   uint32_t eventType = nsContentUtils::GetEventId(aName);
-  nsListenerStruct* ls = FindJSEventListener(eventType, aName);
+  nsListenerStruct* ls = FindEventHandler(eventType, aName);
 
   if (!ls) {
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
     nsCOMPtr<nsIJSEventListener> scriptListener;
     rv = NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
                                aHandler, getter_AddRefs(scriptListener));
     if (NS_SUCCEEDED(rv)) {
       AddEventListener(scriptListener, eventType, aName,
                        NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT);
 
-      ls = FindJSEventListener(eventType, aName);
+      ls = FindEventHandler(eventType, aName);
     }
   } else {
     ls->GetJSListener()->SetHandler(aHandler);
   }
 
   if (NS_SUCCEEDED(rv) && ls) {
     // Set flag to indicate possible need for compilation later
     ls->mHandlerIsString = !aHandler;
@@ -512,21 +512,21 @@ nsEventListenerManager::SetJSEventListen
   } else {
     *aListenerStruct = nullptr;
   }
 
   return rv;
 }
 
 nsresult
-nsEventListenerManager::AddScriptEventListener(nsIAtom *aName,
-                                               const nsAString& aBody,
-                                               uint32_t aLanguage,
-                                               bool aDeferCompilation,
-                                               bool aPermitUntrustedEvents)
+nsEventListenerManager::SetEventHandler(nsIAtom *aName,
+                                        const nsAString& aBody,
+                                        uint32_t aLanguage,
+                                        bool aDeferCompilation,
+                                        bool aPermitUntrustedEvents)
 {
   NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN,
                   "Must know the language for the script event listener");
 
   // |aPermitUntrustedEvents| is set to False for chrome - events
   // *generated* from an unknown source are not allowed.
   // However, for script languages with no 'sandbox', we want to reject
   // such scripts based on the source of their code, not just the source
@@ -622,32 +622,32 @@ nsEventListenerManager::AddScriptEventLi
   }
 
   nsIScriptContext* context = global->GetScriptContext();
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   JSObject* scope = global->GetGlobalJSObject();
 
   nsListenerStruct *ls;
-  rv = SetJSEventListener(context, scope, aName, nullptr,
-                          aPermitUntrustedEvents, &ls);
+  rv = SetEventHandlerInternal(context, scope, aName, nullptr,
+                               aPermitUntrustedEvents, &ls);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aDeferCompilation) {
     return CompileEventHandlerInternal(ls, true, &aBody);
   }
 
   return NS_OK;
 }
 
 void
-nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName)
+nsEventListenerManager::RemoveEventHandler(nsIAtom* aName)
 {
   uint32_t eventType = nsContentUtils::GetEventId(aName);
-  nsListenerStruct* ls = FindJSEventListener(eventType, aName);
+  nsListenerStruct* ls = FindEventHandler(eventType, aName);
 
   if (ls) {
     mListeners.RemoveElementAt(uint32_t(ls - &mListeners.ElementAt(0)));
     mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     mNoListenerForEventAtom = nullptr;
   }
 }
 
@@ -1021,25 +1021,25 @@ nsEventListenerManager::HasUnloadListene
         ls->mEventType == NS_BEFORE_PAGE_UNLOAD) {
       return true;
     }
   }
   return false;
 }
 
 nsresult
-nsEventListenerManager::SetJSEventListenerToJsval(nsIAtom *aEventName,
-                                                  JSContext *cx,
-                                                  JSObject* aScope,
-                                                  const jsval & v)
+nsEventListenerManager::SetEventHandlerToJsval(nsIAtom *aEventName,
+                                               JSContext *cx,
+                                               JSObject* aScope,
+                                               const jsval & v)
 {
   JSObject *handler;
   if (JSVAL_IS_PRIMITIVE(v) ||
       !JS_ObjectIsCallable(cx, handler = JSVAL_TO_OBJECT(v))) {
-    RemoveScriptEventListener(aEventName);
+    RemoveEventHandler(aEventName);
     return NS_OK;
   }
 
   // Now ensure that we're working in the compartment of aScope from now on.
   JSAutoCompartment ac(cx, aScope);
 
   // Rewrap the handler into the new compartment, if needed.
   jsval tempVal = v;
@@ -1052,25 +1052,25 @@ nsEventListenerManager::SetJSEventListen
   // on a dead Window.
   nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(cx, aScope);
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   JSObject *scope = ::JS_GetGlobalForObject(cx, aScope);
   // Untrusted events are always permitted for non-chrome script
   // handlers.
   nsListenerStruct *ignored;
-  return SetJSEventListener(context, scope, aEventName, handler,
-                            !nsContentUtils::IsCallerChrome(), &ignored);
+  return SetEventHandlerInternal(context, scope, aEventName, handler,
+                                 !nsContentUtils::IsCallerChrome(), &ignored);
 }
 
 void
-nsEventListenerManager::GetJSEventListener(nsIAtom *aEventName, jsval *vp)
+nsEventListenerManager::GetEventHandler(nsIAtom *aEventName, jsval *vp)
 {
   uint32_t eventType = nsContentUtils::GetEventId(aEventName);
-  nsListenerStruct* ls = FindJSEventListener(eventType, aEventName);
+  nsListenerStruct* ls = FindEventHandler(eventType, aEventName);
 
   *vp = JSVAL_NULL;
 
   if (!ls) {
     return;
   }
 
   nsIJSEventListener *listener = ls->GetJSListener();
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -96,25 +96,25 @@ public:
   /**
    * Sets the current "inline" event listener for aName to be a
    * function compiled from aFunc if !aDeferCompilation.  If
    * aDeferCompilation, then we assume that we can get the string from
    * mTarget later and compile lazily.
    */
   // XXXbz does that play correctly with nodes being adopted across
   // documents?  Need to double-check the spec here.
-  nsresult AddScriptEventListener(nsIAtom *aName,
-                                  const nsAString& aFunc,
-                                  uint32_t aLanguage,
-                                  bool aDeferCompilation,
-                                  bool aPermitUntrustedEvents);
+  nsresult SetEventHandler(nsIAtom *aName,
+                           const nsAString& aFunc,
+                           uint32_t aLanguage,
+                           bool aDeferCompilation,
+                           bool aPermitUntrustedEvents);
   /**
    * Remove the current "inline" event listener for aName.
    */
-  void RemoveScriptEventListener(nsIAtom *aName);
+  void RemoveEventHandler(nsIAtom *aName);
 
   void HandleEvent(nsPresContext* aPresContext,
                    nsEvent* aEvent, 
                    nsIDOMEvent** aDOMEvent,
                    nsIDOMEventTarget* aCurrentTarget,
                    uint32_t aFlags,
                    nsEventStatus* aEventStatus,
                    nsCxPusher* aPusher)
@@ -237,50 +237,50 @@ protected:
    */
   nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
                                        bool aNeedsCxPush,
                                        const nsAString* aBody);
 
   /**
    * Find the nsListenerStruct for the "inline" event listener for aTypeAtom.
    */
-  nsListenerStruct* FindJSEventListener(uint32_t aEventType, nsIAtom* aTypeAtom);
+  nsListenerStruct* FindEventHandler(uint32_t aEventType, nsIAtom* aTypeAtom);
 
   /**
    * Set the "inline" event listener for aName to aHandler.  aHandler
    * may be null to indicate that we should lazily get and compile the
    * string for this listener.  The nsListenerStruct that results, if
    * any, is returned in aListenerStruct.
    */
-  nsresult SetJSEventListener(nsIScriptContext *aContext,
-                              JSObject* aScopeGlobal,
-                              nsIAtom* aName,
-                              JSObject *aHandler,
-                              bool aPermitUntrustedEvents,
-                              nsListenerStruct **aListenerStruct);
+  nsresult SetEventHandlerInternal(nsIScriptContext *aContext,
+                                   JSObject* aScopeGlobal,
+                                   nsIAtom* aName,
+                                   JSObject *aHandler,
+                                   bool aPermitUntrustedEvents,
+                                   nsListenerStruct **aListenerStruct);
 
   bool IsDeviceType(uint32_t aType);
   void EnableDevice(uint32_t aType);
   void DisableDevice(uint32_t aType);
 
 public:
   /**
    * Set the "inline" event listener for aEventName to |v|.  This
    * might actually remove the event listener, depending on the value
    * of |v|.  Note that on entry to this function cx and aScope might
    * not be in the same compartment, though cx and v are guaranteed to
    * be in the same compartment.
    */
-  nsresult SetJSEventListenerToJsval(nsIAtom *aEventName, JSContext *cx,
-                                     JSObject *aScope, const jsval &v);
+  nsresult SetEventHandlerToJsval(nsIAtom *aEventName, JSContext *cx,
+                                  JSObject *aScope, const jsval &v);
   /**
    * Get the value of the "inline" event listener for aEventName.
    * This may cause lazy compilation if the listener is uncompiled.
    */
-  void GetJSEventListener(nsIAtom *aEventName, jsval *vp);
+  void GetEventHandler(nsIAtom *aEventName, jsval *vp);
 
 protected:
   void AddEventListener(nsIDOMEventListener *aListener, 
                         uint32_t aType,
                         nsIAtom* aTypeAtom,
                         int32_t aFlags);
   void RemoveEventListener(nsIDOMEventListener *aListener,
                            uint32_t aType,
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2835,16 +2835,26 @@ nsEventStateManager::DoScrollText(nsIScr
   nsSize scrollAmount = GetScrollAmount(pc, aEvent, aScrollableFrame);
   nsIntSize scrollAmountInDevPixels(
     pc->AppUnitsToDevPixels(scrollAmount.width),
     pc->AppUnitsToDevPixels(scrollAmount.height));
   nsIntPoint actualDevPixelScrollAmount =
     DeltaAccumulator::GetInstance()->
       ComputeScrollAmountForDefaultAction(aEvent, scrollAmountInDevPixels);
 
+  // Don't scroll around the axis whose overflow style is hidden.
+  nsPresContext::ScrollbarStyles overflowStyle =
+                                   aScrollableFrame->GetScrollbarStyles();
+  if (overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
+    actualDevPixelScrollAmount.x = 0;
+  }
+  if (overflowStyle.mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
+    actualDevPixelScrollAmount.y = 0;
+  }
+
   nsIAtom* origin = nullptr;
   switch (aEvent->deltaMode) {
     case nsIDOMWheelEvent::DOM_DELTA_LINE:
       origin = nsGkAtoms::mouseWheel;
       break;
     case nsIDOMWheelEvent::DOM_DELTA_PAGE:
       origin = nsGkAtoms::pages;
       break;
@@ -2893,30 +2903,54 @@ nsEventStateManager::DoScrollText(nsIScr
     case widget::WheelEvent::SCROLL_SMOOTHLY:
       mode = nsIScrollableFrame::SMOOTH;
       break;
     default:
       MOZ_NOT_REACHED("Invalid scrollType value comes");
       return;
   }
 
+  // XXX When the scroll target came from the wheel transaction manager, there
+  //     may be another scrollable element in its ancestors.  Then, probably we
+  //     shouldn't set overflowDelta even if the event doesn't cause scroll
+  //     actually because the non-zero overflowDelta could cause another action
+  //     such as "back" or "forward" in the history.
+
   nsIntPoint overflow;
   aScrollableFrame->ScrollBy(actualDevPixelScrollAmount,
                              nsIScrollableFrame::DEVICE_PIXELS,
                              mode, &overflow, origin);
 
   if (isDeltaModePixel) {
     aEvent->overflowDeltaX = overflow.x;
     aEvent->overflowDeltaY = overflow.y;
   } else {
     aEvent->overflowDeltaX =
       static_cast<double>(overflow.x) / scrollAmountInDevPixels.width;
     aEvent->overflowDeltaY =
       static_cast<double>(overflow.y) / scrollAmountInDevPixels.height;
   }
+
+  // If CSS overflow properties caused not to scroll, the overflowDelta* values
+  // should be same as delta* values since they may be used as gesture event by
+  // widget.
+  if (overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
+    aEvent->overflowDeltaX = aEvent->deltaX;
+  }
+  if (overflowStyle.mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
+    aEvent->overflowDeltaY = aEvent->deltaY;
+  }
+
+  NS_ASSERTION(aEvent->overflowDeltaX == 0 ||
+    (aEvent->overflowDeltaX > 0) == (actualDevPixelScrollAmount.x > 0),
+    "The sign of overflowDeltaX is different from the scroll direction");
+  NS_ASSERTION(aEvent->overflowDeltaY == 0 ||
+    (aEvent->overflowDeltaY > 0) == (actualDevPixelScrollAmount.y > 0),
+    "The sign of overflowDeltaY is different from the scroll direction");
+
   WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(aEvent);
 }
 
 void
 nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
                                         nsIFrame* targetFrame)
 {
 
@@ -5382,16 +5416,22 @@ nsEventStateManager::WheelPrefs::ApplyUs
 
 void
 nsEventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
                                                    widget::WheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
+  // XXX If the multiplier pref value is negative, the scroll direction was
+  //     changed and caused to scroll different direction.  In such case,
+  //     this method reverts the sign of overflowDelta.  Does it make widget
+  //     happy?  Although, widget can know the pref applied delta values by
+  //     referrencing the deltaX and deltaY of the event.
+
   if (mMultiplierX[index]) {
     aEvent->overflowDeltaX /= mMultiplierX[index];
   }
   if (mMultiplierY[index]) {
     aEvent->overflowDeltaY /= mMultiplierY[index];
   }
 }
 
--- a/content/events/test/window_wheel_default_action.html
+++ b/content/events/test/window_wheel_default_action.html
@@ -512,16 +512,132 @@ function doTestScroll(aSettings, aCallba
     { description: "Not Scroll by momentum pixel scroll if default action is none (action is history)",
       event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
                deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
                lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
                shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
       expected: kNoScroll,
       prepare: function () { SpecialPowers.setIntPref("mousewheel.default.action", 0); },
       cleanup: function () { SpecialPowers.setIntPref("mousewheel.default.action", 1); } },
+
+    // Don't scroll around axis whose overflow style is hidden.
+    { description: "Scroll to only bottom by oblique pixel wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollDown,
+      prepare: function() { gScrollableElement.style.overflowX = "hidden"; } },
+    { description: "Scroll to only bottom by oblique line wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollDown },
+    { description: "Scroll to only bottom by oblique page wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollDown },
+    { description: "Scroll to only top by oblique pixel wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollUp },
+    { description: "Scroll to only top by oblique line wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollUp },
+    { description: "Scroll to only top by oblique page wheel event with overflow-x: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollUp,
+      cleanup: function () { gScrollableElement.style.overflowX = "auto"; } },
+    { description: "Scroll to only right by oblique pixel wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollRight,
+      prepare: function() { gScrollableElement.style.overflowY = "hidden"; } },
+    { description: "Scroll to only right by oblique line wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollRight },
+    { description: "Scroll to only right by oblique page wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollRight },
+    { description: "Scroll to only left by oblique pixel wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollLeft },
+    { description: "Scroll to only top by oblique line wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollLeft },
+    { description: "Scroll to only top by oblique page wheel event with overflow-y: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kScrollLeft,
+      cleanup: function () { gScrollableElement.style.overflowY = "auto"; } },
+    { description: "Don't be scrolled by oblique pixel wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll,
+      prepare: function() { gScrollableElement.style.overflow = "hidden"; } },
+    { description: "Don't be scrolled by oblique line wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll },
+    { description: "Don't be scrolled by oblique page wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll },
+    { description: "Don't be scrolled by oblique pixel wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll },
+    { description: "Don't be scrolled by oblique line wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll },
+    { description: "Don't be scrolled by oblique page wheel event with overflow: hidden",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
+               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
+      expected: kNoScroll,
+      cleanup: function () { gScrollableElement.style.overflow = "auto"; } },
   ];
 
   var description;
 
   var currentTestIndex = -1;
   var isXReverted = (aSettings.deltaMultiplierX < 0);
   var isYReverted = (aSettings.deltaMultiplierY < 0);
 
@@ -551,25 +667,29 @@ function doTestScroll(aSettings, aCallba
         var scrollUp = !isYReverted ? (currentTest.expected & kScrollUp) :
                                       (currentTest.expected & kScrollDown);
         var scrollDown = !isYReverted ? (currentTest.expected & kScrollDown) :
                                         (currentTest.expected & kScrollUp);
         if (scrollUp) {
           ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop);
         } else if (scrollDown) {
           ok(gScrollableElement.scrollTop > 1000, description + "not scrolled down, got " + gScrollableElement.scrollTop);
+        } else {
+          is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
         }
         var scrollLeft = !isXReverted ? (currentTest.expected & kScrollLeft) :
                                         (currentTest.expected & kScrollRight);
         var scrollRight = !isXReverted ? (currentTest.expected & kScrollRight) :
                                          (currentTest.expected & kScrollLeft);
         if (scrollLeft) {
           ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
         } else if (scrollRight) {
           ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
+        } else {
+          is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
         }
       }
       if (currentTest.cleanup) {
         currentTest.cleanup();
       }
       doNextTest();
     }, 10);
   }
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1898,17 +1898,17 @@ nsresult
 nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                    const nsAttrValue* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML) &&
         aValue) {
       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
         "Expected string value for script body");
-      nsresult rv = AddScriptEventListener(aName, aValue->GetStringValue());
+      nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
     else if (aName == nsGkAtoms::dir) {
       Directionality dir;
       if (aValue &&
@@ -2038,17 +2038,17 @@ nsGenericHTMLElement::UnsetAttr(int32_t 
       // Have to unregister before clearing flag. See UnregAccessKey
       UnregAccessKey();
       UnsetFlags(NODE_HAS_ACCESSKEY);
     }
     else if (nsContentUtils::IsEventAttributeName(aAttribute,
                                                   EventNameType_HTML)) {
       nsEventListenerManager* manager = GetListenerManager(false);
       if (manager) {
-        manager->RemoveScriptEventListener(aAttribute);
+        manager->RemoveEventHandler(aAttribute);
       }
     }
 
     // Remove dataset property if necessary.
     nsDOMSlots *slots = GetExistingDOMSlots();
     if (slots && slots->mDataset) {
       slots->mDataset->RemoveProp(aAttribute);
     }
@@ -4080,17 +4080,17 @@ nsGenericHTMLElement::RecompileScriptEve
 
         nsIAtom *attr = name->Atom();
         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_HTML)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
-        AddScriptEventListener(attr, value, true);
+        SetEventHandler(attr, value, true);
     }
 }
 
 bool
 nsGenericHTMLElement::IsEditableRoot() const
 {
   nsIDocument *document = GetCurrentDoc();
   if (!document) {
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -917,17 +917,17 @@ NS_IMETHODIMP
 nsHTMLInputElement::SetHeight(uint32_t aHeight)
 {
   return nsGenericHTMLElement::SetUnsignedIntAttr(nsGkAtoms::height, aHeight);
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::GetIndeterminate(bool* aValue)
 {
-  *aValue = mIndeterminate;
+  *aValue = Indeterminate();
   return NS_OK;
 }
 
 nsresult
 nsHTMLInputElement::SetIndeterminateInternal(bool aValue,
                                              bool aShouldInvalidate)
 {
   mIndeterminate = aValue;
@@ -1636,17 +1636,17 @@ nsHTMLInputElement::SetValueChanged(bool
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHTMLInputElement::GetChecked(bool* aChecked)
 {
-  *aChecked = mChecked;
+  *aChecked = Checked();
   return NS_OK;
 }
 
 void
 nsHTMLInputElement::SetCheckedChanged(bool aCheckedChanged)
 {
   DoSetCheckedChanged(aCheckedChanged, true);
 }
--- a/content/html/content/src/nsHTMLInputElement.h
+++ b/content/html/content/src/nsHTMLInputElement.h
@@ -281,20 +281,23 @@ public:
    * @param aIsFocused Whether the element is currently focused.
    *
    * @note The caller is responsible to call ContentStatesChanged.
    */
   void UpdateValidityUIBits(bool aIsFocused);
 
   bool DefaultChecked() const {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::checked);
-  }
-
-  /**
-   * Fires change event if mFocusedValue and current value held are unequal.
+  }
+
+  bool Indeterminate() const { return mIndeterminate; }
+  bool Checked() const { return mChecked; }
+
+  /**
+   * Fires change event if mFocusedValue and current value held are unequal.
    */
   void FireChangeEventIfNeeded();
 
 protected:
   // Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
   // by the nsITextControlElement version.
   using nsGenericHTMLFormElement::IsSingleLineTextControl;
 
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -175,16 +175,17 @@ nsHTMLLinkElement::SetDisabled(bool aDis
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Charset, charset)
 NS_IMPL_URI_ATTR(nsHTMLLinkElement, Href, href)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Hreflang, hreflang)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Media, media)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rel, rel)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
 NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
+NS_IMPL_STRING_ATTR(nsHTMLLinkElement, CrossOrigin, crossorigin)
 
 void
 nsHTMLLinkElement::GetItemValueText(nsAString& aValue)
 {
   GetHref(aValue);
 }
 
 void
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -321,16 +321,17 @@ MOCHITEST_FILES = \
 		file_iframe_sandbox_top_navigation_fail.html \
 		test_iframe_sandbox_plugins.html \
 		file_iframe_sandbox_f_if1.html \
 		file_iframe_sandbox_f_if2.html \
 		file_iframe_sandbox_f_if2.html^headers^ \
 		test_iframe_sandbox_workers.html \
 		file_iframe_sandbox_g_if1.html \
 		file_iframe_sandbox_worker.js \
+		test_bug786564.html \
 		$(NULL)
 
 MOCHITEST_BROWSER_FILES = \
 		browser_bug649778.js \
 		file_bug649778.html \
 		file_bug649778.html^headers^ \
 		$(NULL)
 
copy from content/html/content/test/test_bug742549.html
copy to content/html/content/test/test_bug786564.html
--- a/content/html/content/test/test_bug742549.html
+++ b/content/html/content/test/test_bug786564.html
@@ -1,40 +1,35 @@
 <!DOCTYPE HTML>
 <html>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=742549
+https://bugzilla.mozilla.org/show_bug.cgi?id=786564
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 742549</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="reflect.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742549">Mozilla Bug 742549</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786564">Mozilla Bug 786564</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-/** Test for Bug 742549 **/
-var els = [ document.createElement("script"),
-            document.createElementNS("http://www.w3.org/2000/svg", "script") ]
-
-for (var i = 0; i < els.length; ++i) {
+/** Test for Bug 786564 **/
   reflectString({
-    element: els[i],
+    element: document.createElement("link"),
     attribute: { content: "crossorigin", idl: "crossOrigin" },
     otherValues: [ "anonymous", "use-credentials" ]
   })
-}
 
 
 
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -913,17 +913,18 @@ ChannelMediaResource::PossiblyResume()
   }
 }
 
 class FileMediaResource : public MediaResource
 {
 public:
   FileMediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
     MediaResource(aDecoder, aChannel, aURI), mSize(-1),
-    mLock("FileMediaResource.mLock")
+    mLock("FileMediaResource.mLock"),
+    mSizeInitialized(false)
   {
   }
   ~FileMediaResource()
   {
   }
 
   // Main thread
   virtual nsresult Open(nsIStreamListener** aStreamListener);
@@ -950,17 +951,21 @@ public:
   virtual void    Pin() {}
   virtual void    Unpin() {}
   virtual double  GetDownloadRate(bool* aIsReliable)
   {
     // The data's all already here
     *aIsReliable = true;
     return 100*1024*1024; // arbitray, use 100MB/s
   }
-  virtual int64_t GetLength() { return mSize; }
+  virtual int64_t GetLength() {
+    MutexAutoLock lock(mLock);
+    EnsureLengthInitialized();
+    return mSize;
+  }
   virtual int64_t GetNextCachedData(int64_t aOffset)
   {
     return (aOffset < mSize) ? aOffset : -1;
   }
   virtual int64_t GetCachedDataEnd(int64_t aOffset) { return NS_MAX(aOffset, mSize); }
   virtual bool    IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
   virtual bool    IsSuspendedByCache(MediaResource** aActiveResource)
   {
@@ -969,16 +974,19 @@ public:
     }
     return false;
   }
   virtual bool    IsSuspended() { return false; }
 
   nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
 
 private:
+  // Ensures mSize is initialized, if it can be.
+  void EnsureLengthInitialized();
+
   // The file size, or -1 if not known. Immutable after Open().
   int64_t mSize;
 
   // This lock handles synchronisation between calls to Close() and
   // the Read, Seek, etc calls. Close must not be called while a
   // Read or Seek is in progress since it resets various internal
   // values to null.
   // This lock protects mSeekable and mInput.
@@ -986,16 +994,21 @@ private:
 
   // Seekable stream interface to file. This can be used from any
   // thread.
   nsCOMPtr<nsISeekableStream> mSeekable;
 
   // Input stream for the media data. This can be used from any
   // thread.
   nsCOMPtr<nsIInputStream>  mInput;
+
+  // Whether we've attempted to initialize mSize. Note that mSize can be -1
+  // when mSizeInitialized is true if we tried and failed to get the size
+  // of the file.
+  bool mSizeInitialized;
 };
 
 class LoadedEvent : public nsRunnable
 {
 public:
   LoadedEvent(nsMediaDecoder* aDecoder) :
     mDecoder(aDecoder)
   {
@@ -1010,18 +1023,37 @@ public:
     mDecoder->NotifyDownloadEnded(NS_OK);
     return NS_OK;
   }
 
 private:
   nsRefPtr<nsMediaDecoder> mDecoder;
 };
 
+void FileMediaResource::EnsureLengthInitialized()
+{
+  mLock.AssertCurrentThreadOwns();
+  if (mSizeInitialized) {
+    return;
+  }
+  mSizeInitialized = true;
+  // Get the file size and inform the decoder.
+  uint64_t size;
+  nsresult res = mInput->Available(&size);
+  if (NS_SUCCEEDED(res) && size <= PR_INT64_MAX) {
+    mSize = (int64_t)size;
+    nsCOMPtr<nsIRunnable> event = new LoadedEvent(mDecoder);
+    NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
+  }
+}
+
 nsresult FileMediaResource::GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
 {
+  MutexAutoLock lock(mLock);
+  EnsureLengthInitialized();
   if (mSize == -1) {
     return NS_ERROR_FAILURE;
   }
   aRanges.AppendElement(MediaByteRange(0, mSize));
   return NS_OK;
 }
 
 nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener)
@@ -1066,26 +1098,16 @@ nsresult FileMediaResource::Open(nsIStre
   if (!mSeekable) {
     // XXX The file may just be a .url or similar
     // shortcut that points to a Web site. We need to fix this by
     // doing an async open and waiting until we locate the real resource,
     // then using that (if it's still a file!).
     return NS_ERROR_FAILURE;
   }
 
-  // Get the file size and inform the decoder.
-  uint64_t size;
-  rv = mInput->Available(&size);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(size <= PR_INT64_MAX, NS_ERROR_FILE_TOO_BIG);
- 
-  mSize = (int64_t)size;
-
-  nsCOMPtr<nsIRunnable> event = new LoadedEvent(mDecoder);
-  NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 nsresult FileMediaResource::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   MutexAutoLock lock(mLock);
@@ -1135,16 +1157,17 @@ MediaResource* FileMediaResource::CloneD
     return nullptr;
 
   return new FileMediaResource(aDecoder, channel, mURI);
 }
 
 nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
 {
   MutexAutoLock lock(mLock);
+  EnsureLengthInitialized();
   if (!mInput || !mSeekable)
     return NS_ERROR_FAILURE;
   int64_t offset = 0;
   nsresult res = mSeekable->Tell(&offset);
   NS_ENSURE_SUCCESS(res,res);
   res = mSeekable->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
   NS_ENSURE_SUCCESS(res,res);
   uint32_t bytesRead = 0;
@@ -1164,38 +1187,41 @@ nsresult FileMediaResource::ReadFromCach
 
   // Else we succeed if the reset-seek succeeds.
   return seekres;
 }
 
 nsresult FileMediaResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
 {
   MutexAutoLock lock(mLock);
+  EnsureLengthInitialized();
   if (!mInput)
     return NS_ERROR_FAILURE;
   return mInput->Read(aBuffer, aCount, aBytes);
 }
 
 nsresult FileMediaResource::Seek(int32_t aWhence, int64_t aOffset)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
   MutexAutoLock lock(mLock);
   if (!mSeekable)
     return NS_ERROR_FAILURE;
+  EnsureLengthInitialized();
   return mSeekable->Seek(aWhence, aOffset);
 }
 
 int64_t FileMediaResource::Tell()
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
   MutexAutoLock lock(mLock);
   if (!mSeekable)
     return 0;
+  EnsureLengthInitialized();
 
   int64_t offset = 0;
   mSeekable->Tell(&offset);
   return offset;
 }
 
 MediaResource*
 MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -909,20 +909,17 @@ MediaStreamGraphImpl::UpdateStreamOrderF
   if (stream->mIsOnOrderingStack) {
     for (int32_t i = aStack->Length() - 1; ; --i) {
       aStack->ElementAt(i)->AsProcessedStream()->mInCycle = true;
       if (aStack->ElementAt(i) == stream)
         break;
     }
     return;
   }
-  SourceMediaStream* s = stream->AsSourceStream();
-  if (s) {
-    DetermineWhetherStreamIsConsumed(stream);
-  }
+  DetermineWhetherStreamIsConsumed(stream);
   ProcessedMediaStream* ps = stream->AsProcessedStream();
   if (ps) {
     aStack->AppendElement(stream);
     stream->mIsOnOrderingStack = true;
     for (uint32_t i = 0; i < ps->mInputs.Length(); ++i) {
       MediaStream* source = ps->mInputs[i]->mSource;
       if (!source->mHasBeenOrdered) {
         nsRefPtr<MediaStream> s = source;
@@ -941,16 +938,17 @@ void
 MediaStreamGraphImpl::UpdateStreamOrder()
 {
   nsTArray<nsRefPtr<MediaStream> > oldStreams;
   oldStreams.SwapElements(mStreams);
   for (uint32_t i = 0; i < oldStreams.Length(); ++i) {
     MediaStream* stream = oldStreams[i];
     stream->mHasBeenOrdered = false;
     stream->mKnowIsConsumed = false;
+    stream->mIsConsumed = false;
     stream->mIsOnOrderingStack = false;
     stream->mInBlockingSet = false;
     ProcessedMediaStream* ps = stream->AsProcessedStream();
     if (ps) {
       ps->mInCycle = false;
     }
   }
 
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -353,16 +353,20 @@ nsSMILAnimationController::DoSample()
 
 void
 nsSMILAnimationController::DoSample(bool aSkipUnchangedContainers)
 {
   if (!mDocument) {
     NS_ERROR("Shouldn't be sampling after document has disconnected");
     return;
   }
+  if (mRunningSample) {
+    NS_ERROR("Shouldn't be recursively sampling");
+    return;
+  }
 
   mResampleNeeded = false;
   // Set running sample flag -- do this before flushing styles so that when we
   // flush styles we don't end up requesting extra samples
   mRunningSample = true;
   nsCOMPtr<nsIDocument> kungFuDeathGrip(mDocument);  // keeps 'this' alive too
   mDocument->FlushPendingNotifications(Flush_Style);
 
--- a/content/smil/nsSMILInstanceTime.cpp
+++ b/content/smil/nsSMILInstanceTime.cpp
@@ -162,19 +162,18 @@ nsSMILInstanceTime::IsDependentOn(const 
 
   const nsSMILInstanceTime* myBaseTime = GetBaseTime();
   if (!myBaseTime)
     return false;
 
   if (myBaseTime == &aOther)
     return true;
 
-  // mVisited is mutable
-  mozilla::AutoRestore<bool> setVisited(const_cast<nsSMILInstanceTime*>(this)->mVisited);
-  const_cast<nsSMILInstanceTime*>(this)->mVisited = true;
+  mozilla::AutoRestore<bool> setVisited(mVisited);
+  mVisited = true;
   return myBaseTime->IsDependentOn(aOther);
 }
 
 const nsSMILInstanceTime*
 nsSMILInstanceTime::GetBaseTime() const
 {
   if (!mBaseInterval) {
     return nullptr;
--- a/content/smil/nsSMILInstanceTime.h
+++ b/content/smil/nsSMILInstanceTime.h
@@ -127,17 +127,17 @@ protected:
     kFromDOM = 4,
 
     // Indicates that this instance time was used as the endpoint of an interval
     // that has been filtered or removed. However, since it is a dynamic time it
     // should be preserved and not filtered.
     kWasDynamicEndpoint = 8
   };
   uint8_t       mFlags;   // Combination of kDynamic, kMayUpdate, etc.
-  bool          mVisited; // (mutable) Cycle tracking
+  mutable bool  mVisited; // Cycle tracking
 
   // Additional reference count to determine if this instance time is currently
   // used as a fixed endpoint in any intervals. Instance times that are used in
   // this way should not be removed when the owning nsSMILTimedElement removes
   // instance times in response to a restart or in an attempt to free up memory
   // by filtering out old instance times.
   //
   // Instance times are only shared in a few cases, namely:
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -246,18 +246,18 @@ nsSVGElement::AfterSetAttr(int32_t aName
   // GetContentStyleRule()
   if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
     mContentStyleRule = nullptr;
   }
 
   if (IsEventName(aName) && aValue) {
     NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
       "Expected string value for script body");
-    nsresult rv = AddScriptEventListener(GetEventNameForAttr(aName),
-                                         aValue->GetStringValue());
+    nsresult rv = SetEventHandler(GetEventNameForAttr(aName),
+                                  aValue->GetStringValue());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
 }
 
 bool
 nsSVGElement::ParseAttribute(int32_t aNamespaceID,
@@ -601,17 +601,17 @@ nsSVGElement::UnsetAttrInternal(int32_t 
     // If this is an svg presentation attribute, remove rule to force an update
     if (IsAttributeMapped(aName))
       mContentStyleRule = nullptr;
 
     if (IsEventName(aName)) {
       nsEventListenerManager* manager = GetListenerManager(false);
       if (manager) {
         nsIAtom* eventName = GetEventNameForAttr(aName);
-        manager->RemoveScriptEventListener(eventName);
+        manager->RemoveEventHandler(eventName);
       }
       return;
     }
     
     // Check if this is a length attribute going away
     LengthAttributesInfo lenInfo = GetLengthInfo();
 
     for (uint32_t i = 0; i < lenInfo.mLengthCount; i++) {
@@ -2438,17 +2438,17 @@ nsSVGElement::RecompileScriptEventListen
 
     nsIAtom *attr = name->Atom();
     if (!IsEventName(attr)) {
       continue;
     }
 
     nsAutoString value;
     GetAttr(kNameSpaceID_None, attr, value);
-    AddScriptEventListener(GetEventNameForAttr(attr), value, true);
+    SetEventHandler(GetEventNameForAttr(attr), value, true);
   }
 }
 
 nsISMILAttr*
 nsSVGElement::GetAnimatedAttr(int32_t aNamespaceID, nsIAtom* aName)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     // We check mapped-into-style attributes first so that animations
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -599,17 +599,17 @@ NS_IMETHODIMP
 nsSVGSVGElement::GetElementById(const nsAString & elementId, nsIDOMElement **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   nsresult rv = NS_OK;
   nsAutoString selector(NS_LITERAL_STRING("#"));
   nsStyleUtil::AppendEscapedCSSIdent(PromiseFlatString(elementId), selector);
-  nsIContent* element = nsGenericElement::doQuerySelector(this, selector, &rv);
+  nsIContent* element = QuerySelector(selector, &rv);
   if (NS_SUCCEEDED(rv) && element) {
     return CallQueryInterface(element, _retval);
   }
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGFitToViewBox methods
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -651,17 +651,17 @@ nsXULElement::AddListenerFor(const nsAtt
     // Eventlistenener-attributes are always in the null namespace
     if (aName.IsAtom()) {
         nsIAtom *attr = aName.Atom();
         MaybeAddPopupListener(attr);
         if (aCompileEventHandlers &&
             nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             nsAutoString value;
             GetAttr(kNameSpaceID_None, attr, value);
-            AddScriptEventListener(attr, value, true);
+            SetEventHandler(attr, value, true);
         }
     }
 }
 
 void
 nsXULElement::MaybeAddPopupListener(nsIAtom* aLocalName)
 {
     // If appropriate, add a popup listener. Called when we change the
@@ -914,21 +914,21 @@ nsXULElement::AfterSetAttr(int32_t aName
 {
     if (aNamespaceID == kNameSpaceID_None) {
         if (aValue) {
             // Add popup and event listeners. We can't call AddListenerFor since
             // the attribute isn't set yet.
             MaybeAddPopupListener(aName);
             if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL)) {
                 if (aValue->Type() == nsAttrValue::eString) {
-                    AddScriptEventListener(aName, aValue->GetStringValue(), true);
+                    SetEventHandler(aName, aValue->GetStringValue(), true);
                 } else {
                     nsAutoString body;
                     aValue->ToString(body);
-                    AddScriptEventListener(aName, body, true);
+                    SetEventHandler(aName, body, true);
                 }
             }
     
             // Hide chrome if needed
             if (mNodeInfo->Equals(nsGkAtoms::window)) {
                 if (aName == nsGkAtoms::hidechrome) {
                     HideWindowChrome(
                       aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
@@ -1848,17 +1848,17 @@ nsXULElement::RecompileScriptEventListen
 
         nsIAtom *attr = name->Atom();
         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
-        AddScriptEventListener(attr, value, true);
+        SetEventHandler(attr, value, true);
     }
 }
 
 NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsXULPrototypeNode)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXULPrototypeNode)
     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
--- a/content/xul/templates/src/nsXULContentUtils.cpp
+++ b/content/xul/templates/src/nsXULContentUtils.cpp
@@ -239,25 +239,25 @@ nsXULContentUtils::GetTextForNode(nsIRDF
         if (NS_FAILED(rv)) return rv;
 
         aResult = p;
         return NS_OK;
     }
 
     nsCOMPtr<nsIRDFDate> dateLiteral = do_QueryInterface(aNode);
     if (dateLiteral) {
-        int64_t	value;
+        PRTime value;
         rv = dateLiteral->GetValue(&value);
         if (NS_FAILED(rv)) return rv;
 
         nsAutoString str;
         rv = gFormat->FormatPRTime(nullptr /* nsILocale* locale */,
                                   kDateFormatShort,
                                   kTimeFormatSeconds,
-                                  PRTime(value),
+                                  value,
                                   str);
         aResult.Assign(str);
 
         if (NS_FAILED(rv)) return rv;
 
         return NS_OK;
     }
 
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -255,17 +255,17 @@ nsDSURIContentListener::SetParentContent
         mParentContentListener = nullptr;
     }
     return NS_OK;
 }
 
 bool nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIRequest *request,
                                                         const nsAString& policy) {
     static const char allowFrom[] = "allow-from ";
-    const PRUint32 allowFromLen = ArrayLength(allowFrom) - 1;
+    const uint32_t allowFromLen = ArrayLength(allowFrom) - 1;
     bool isAllowFrom =
         StringHead(policy, allowFromLen).LowerCaseEqualsLiteral(allowFrom);
 
     // return early if header does not have one of the values with meaning
     if (!policy.LowerCaseEqualsLiteral("deny") &&
         !policy.LowerCaseEqualsLiteral("sameorigin") &&
         !isAllowFrom)
         return true;
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -70,25 +70,32 @@ PARALLEL_DIRS += \
   workers \
   camera \
   $(NULL)
 
 ifdef MOZ_B2G_RIL
 PARALLEL_DIRS += \
   telephony \
   wifi \
+  icc \
   $(NULL)
 endif
 
 ifdef MOZ_B2G_BT
 PARALLEL_DIRS += \
   bluetooth \
   $(NULL)
 endif
 
+ifdef MOZ_PAY
+PARALLEL_DIRS += \
+  payment \
+  $(NULL)
+endif
+
 # bindings/test is here, because it needs to build after bindings/, and
 # we build subdirectories before ourselves.
 TEST_DIRS += \
   tests \
   imptests \
   bindings/test \
   $(NULL)
 
--- a/dom/apps/src/AppsService.js
+++ b/dom/apps/src/AppsService.js
@@ -1,79 +1,54 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict"
 
 function debug(s) {
-  //dump("-*- AppsService: " + s + "\n");
+  //dump("-*- AppsService.js: " + s + "\n");
 }
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
 
 function AppsService()
 {
   debug("AppsService Constructor");
-  this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
-                  .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-  debug("inParent: " + this.inParent);
-  if (this.inParent) {
-    Cu.import("resource://gre/modules/Webapps.jsm");
-  } else {
-    this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
-                .getService(Ci.nsISyncMessageSender);
-  }
+  let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
+                   .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+  debug("inParent: " + inParent);
+  Cu.import(inParent ? "resource://gre/modules/Webapps.jsm" :
+                       "resource://gre/modules/AppsServiceChild.jsm");
 }
 
 AppsService.prototype = {
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("GetAppByManifestURL( " + aManifestURL + " )");
-    if (this.inParent) {
-      return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
-    } else {
-      return this.cpmm.sendSyncMessage("WebApps:GetAppByManifestURL",
-                                       { url: aManifestURL })[0];
-    }
+    return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
   },
 
   getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
     debug("getAppLocalIdByManifestURL( " + aManifestURL + " )");
-    if (this.inParent) {
-      return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
-    } else {
-      let res = this.cpmm.sendSyncMessage("WebApps:GetAppLocalIdByManifestURL",
-                                          { url: aManifestURL })[0];
-      return res.id;
-    }
+    return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
   },
 
   getAppByLocalId: function getAppByLocalId(aLocalId) {
     debug("getAppByLocalId( " + aLocalId + " )");
-    if (this.inParent) {
-      return DOMApplicationRegistry.getAppByLocalId(aLocalId);
-    } else {
-      return this.cpmm.sendSyncMessage("WebApps:GetAppByLocalId",
-                                       { id: aLocalId })[0];
-    }
+    return DOMApplicationRegistry.getAppByLocalId(aLocalId);
   },
 
   getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
     debug("getManifestURLByLocalId( " + aLocalId + " )");
-    if (this.inParent) {
-      return DOMApplicationRegistry.getManifestURLByLocalId(aLocalId);
-    } else {
-      return this.cpmm.sendSyncMessage("WebApps:GetManifestURLByLocalId",
-                                       { id: aLocalId })[0];
-    }
+    return DOMApplicationRegistry.getManifestURLByLocalId(aLocalId);
   },
 
   classID : APPS_SERVICE_CID,
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
new file mode 100644
--- /dev/null
+++ b/dom/apps/src/AppsServiceChild.jsm
@@ -0,0 +1,82 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+// This module exposes a subset of the functionnalities of the parent DOM
+// Registry to content processes, to be be used from the AppsService component.
+
+let EXPORTED_SYMBOLS = ["DOMApplicationRegistry"];
+
+Cu.import("resource://gre/modules/AppsUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function debug(s) {
+  //dump("-*- AppsServiceChild.jsm: " + s + "\n");
+}
+
+let DOMApplicationRegistry = {
+  init: function init() {
+    debug("init");
+    this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+                  .getService(Ci.nsISyncMessageSender);
+
+    ["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
+      this.cpmm.addMessageListener(aMsgName, this);
+    }).bind(this));
+
+    // We need to prime the cache with the list of apps.
+    // XXX shoud we do this async and block callers if it's not yet there?
+    this.webapps = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
+    Services.obs.addObserver(this, "xpcom-shutdown", false);
+  },
+
+  observe: function(aSubject, aTopic, aData) {
+    // cpmm.addMessageListener causes the DOMApplicationRegistry object to live
+    // forever if we don't clean up properly.
+    this.webapps = null;
+    ["Webapps:AddApp", "Webapps:RemoveApp"].forEach((function(aMsgName) {
+      this.cpmm.removeMessageListener(aMsgName, this);
+    }).bind(this));
+  },
+
+  receiveMessage: function receiveMessage(aMessage) {
+    debug("Received " + aMessage.name + " message.");
+    let msg = aMessage.json;
+    switch (aMessage.name) {
+      case "Webapps:AddApp":
+        this.webapps[msg.id] = msg.app;
+        break;
+      case "Webapps:RemoveApp":
+        delete this.webapps[msg.id];
+        break;
+    }
+  },
+
+  getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
+    debug("getAppByManifestURL " + aManifestURL);
+    return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
+  },
+
+  getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
+    debug("getAppLocalIdByManifestURL " + aManifestURL);
+    return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
+  },
+
+  getAppByLocalId: function getAppByLocalId(aLocalId) {
+    debug("getAppByLocalId " + aLocalId);
+    return AppsUtils.getAppByLocalId(this.webapps, aLocalId);
+  },
+
+  getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
+    debug("getManifestURLByLocalId " + aLocalId);
+    return AppsUtils.getManifestURLByLocalId(this.webapps, aLocalId);
+  }
+}
+
+DOMApplicationRegistry.init();
new file mode 100644
--- /dev/null
+++ b/dom/apps/src/AppsUtils.jsm
@@ -0,0 +1,108 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+// Shared code for AppsServiceChild.jsm and Webapps.jsm
+
+let EXPORTED_SYMBOLS = ["AppsUtils"];
+
+function debug(s) {
+  //dump("-*- AppsUtils.jsm: " + s + "\n");
+}
+
+let AppsUtils = {
+  // Clones a app, without the manifest.
+  cloneAppObject: function cloneAppObject(aApp) {
+    return {
+      installOrigin: aApp.installOrigin,
+      origin: aApp.origin,
+      receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
+      installTime: aApp.installTime,
+      manifestURL: aApp.manifestURL,
+      appStatus: aApp.appStatus,
+      localId: aApp.localId,
+      progress: aApp.progress || 0.0,
+      status: aApp.status || "installed"
+    };
+  },
+
+  cloneAsMozIApplication: function cloneAsMozIApplication(aApp) {
+    let res = this.cloneAppObject(aApp);
+    res.hasPermission = function(aPermission) {
+      let uri = Services.io.newURI(this.origin, null, null);
+      let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                     .getService(Ci.nsIScriptSecurityManager);
+      // This helper checks an URI inside |aApp|'s origin and part of |aApp| has a
+      // specific permission. It is not checking if browsers inside |aApp| have such
+      // permission.
+      let principal = secMan.getAppCodebasePrincipal(uri, aApp.localId,
+                                                     /*mozbrowser*/false);
+      let perm = Services.perms.testExactPermissionFromPrincipal(principal,
+                                                                 aPermission);
+      return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
+    };
+    res.QueryInterface = XPCOMUtils.generateQI([Ci.mozIDOMApplication,
+                                                Ci.mozIApplication]);
+    return res;
+  },
+
+  getAppByManifestURL: function getAppByManifestURL(aApps, aManifestURL) {
+    debug("getAppByManifestURL " + aManifestURL);
+    // This could be O(1) if |webapps| was a dictionary indexed on manifestURL
+    // which should be the unique app identifier.
+    // It's currently O(n).
+    for (let id in aApps) {
+      let app = aApps[id];
+      if (app.manifestURL == aManifestURL) {
+        return this.cloneAsMozIApplication(app);
+      }
+    }
+
+    return null;
+  },
+
+  getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aApps, aManifestURL) {
+    debug("getAppLocalIdByManifestURL " + aManifestURL);
+    for (let id in aApps) {
+      if (aApps[id].manifestURL == aManifestURL) {
+        return aApps[id].localId;
+      }
+    }
+
+    return Ci.nsIScriptSecurityManager.NO_APP_ID;
+  },
+
+  getAppByLocalId: function getAppByLocalId(aApps, aLocalId) {
+    debug("getAppByLocalId " + aLocalId);
+    for (let id in aApps) {
+      let app = aApps[id];
+      if (app.localId == aLocalId) {
+        return this.cloneAsMozIApplication(app);
+      }
+    }
+
+    return null;
+  },
+
+  getManifestURLByLocalId: function getManifestURLByLocalId(aApps, aLocalId) {
+    debug("getManifestURLByLocalId " + aLocalId);
+    for (let id in aApps) {
+      let app = aApps[id];
+      if (app.localId == aLocalId) {
+        return app.manifestURL;
+      }
+    }
+
+    return "";
+  }
+}
--- a/dom/apps/src/Makefile.in
+++ b/dom/apps/src/Makefile.in
@@ -13,11 +13,13 @@ EXTRA_COMPONENTS = \
   AppsService.js \
   AppsService.manifest \
   Webapps.js \
   Webapps.manifest \
   $(NULL)
 
 EXTRA_PP_JS_MODULES += \
   Webapps.jsm \
+  AppsServiceChild.jsm \
+  AppsUtils.jsm \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -15,17 +15,17 @@ Cu.import("resource://gre/modules/Object
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsIMessageSender");
 
 function convertAppsArray(aApps, aWindow) {
   let apps = Cu.createArrayIn(aWindow);
   for (let i = 0; i < aApps.length; i++) {
     let app = aApps[i];
-    apps.push(createApplicationObject(aWindow, app.origin, app.manifest, app.manifestURL, 
+    apps.push(createApplicationObject(aWindow, app.origin, app.manifest, app.manifestURL,
                                       app.receipts, app.installOrigin, app.installTime));
   }
 
   return apps;
 }
 
 function WebappsRegistry() {
 }
@@ -50,16 +50,24 @@ WebappsRegistry.prototype = {
     if (aManifest.installs_allowed_from) {
       return aManifest.installs_allowed_from.some(function(aOrigin) {
         return aOrigin == "*" || aOrigin == aInstallOrigin;
       });
     }
     return true;
   },
 
+  // Hosted apps can't be trusted or certified, so just check that the
+  // manifest doesn't ask for those.
+  checkAppStatus: function(aManifest) {
+    let manifestStatus = aManifest.type || "web";
+    return (Services.prefs.getBoolPref("dom.mozApps.dev_mode") ||
+            manifestStatus === "web");
+  },
+
   receiveMessage: function(aMessage) {
     let msg = aMessage.json;
     if (msg.oid != this._id)
       return
     let req = this.getRequest(msg.requestID);
     if (!req)
       return;
     let app = msg.app;
@@ -87,56 +95,60 @@ WebappsRegistry.prototype = {
         Services.DOMRequest.fireError(req, "ERROR");
         break;
     }
     this.removeRequest(msg.requestID);
   },
 
   _getOrigin: function(aURL) {
     let uri = Services.io.newURI(aURL, null, null);
-    return uri.prePath; 
+    return uri.prePath;
   },
 
   // mozIDOMApplicationRegistry implementation
-  
+
   install: function(aURL, aParams) {
     let installURL = this._window.location.href;
     let installOrigin = this._getOrigin(installURL);
     let request = this.createRequest();
     let requestID = this.getRequestId(request);
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", aURL, true);
     xhr.channel.loadFlags |= Ci.nsIRequest.VALIDATE_ALWAYS;
 
     xhr.addEventListener("load", (function() {
       if (xhr.status == 200) {
         try {
           let manifest = JSON.parse(xhr.responseText, installOrigin);
           if (!this.checkManifest(manifest, installOrigin)) {
             Services.DOMRequest.fireError(request, "INVALID_MANIFEST");
           } else {
-            let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : [];
-            let categories = (aParams && aParams.categories && Array.isArray(aParams.categories)) ? aParams.categories : [];
-            cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
-                                                              origin: this._getOrigin(aURL),
-                                                              manifestURL: aURL,
-                                                              manifest: manifest,
-                                                              receipts: receipts,
-                                                              categories: categories },
-                                                              from: installURL,
-                                                              oid: this._id,
-                                                              requestID: requestID });
+            if (!this.checkAppStatus(manifest)) {
+              Services.DOMRequest.fireError(request, "INVALID_SECURITY_LEVEL");
+            } else {
+              let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : [];
+              let categories = (aParams && aParams.categories && Array.isArray(aParams.categories)) ? aParams.categories : [];
+              cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
+                                                                origin: this._getOrigin(aURL),
+                                                                manifestURL: aURL,
+                                                                manifest: manifest,
+                                                                receipts: receipts,
+                                                                categories: categories },
+                                                                from: installURL,
+                                                                oid: this._id,
+                                                                requestID: requestID });
+            }
           }
         } catch(e) {
           Services.DOMRequest.fireError(request, "MANIFEST_PARSE_ERROR");
         }
       }
       else {
         Services.DOMRequest.fireError(request, "MANIFEST_URL_ERROR");
-      }      
+      }
     }).bind(this), false);
 
     xhr.addEventListener("error", (function() {
       Services.DOMRequest.fireError(request, "NETWORK_ERROR");
     }).bind(this), false);
 
     xhr.send(null);
     return request;
@@ -190,21 +202,21 @@ WebappsRegistry.prototype = {
   init: function(aWindow) {
     this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
                               "Webapps:GetInstalled:Return:OK",
                               "Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
 
     let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     this._id = util.outerWindowID;
   },
-  
+
   classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistry, Ci.nsIDOMGlobalPropertyInitializer]),
-  
+
   classInfo: XPCOMUtils.generateCI({classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
                                     contractID: "@mozilla.org/webapps;1",
                                     interfaces: [Ci.mozIDOMApplicationRegistry],
                                     flags: Ci.nsIClassInfo.DOM_OBJECT,
                                     classDescription: "Webapps Registry"})
 }
 
 /**
@@ -289,17 +301,17 @@ WebappsApplication.prototype = {
         Services.DOMRequest.fireSuccess(req, msg.origin);
         break;
       case "Webapps:Uninstall:Return:KO":
         Services.DOMRequest.fireError(req, "NOT_INSTALLED");
         break;
       case "Webapps:OfflineCache":
         if (msg.manifest != this.manifestURL)
           return;
-        
+
         this.status = msg.status;
         if (this._onprogress) {
           let event = new this._window.MozApplicationEvent("applicationinstall", { application: this });
           this._onprogress.handleEvent(event);
         }
         break;
     }
   },
@@ -388,41 +400,41 @@ WebappsApplicationMgmt.prototype = {
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
   },
 
   receiveMessage: function(aMessage) {
     var msg = aMessage.json;
     let req = this.getRequest(msg.requestID);
     // We want Webapps:Install:Return:OK and Webapps:Uninstall:Return:OK to be boradcasted
     // to all instances of mozApps.mgmt
-    if (!((msg.oid == this._id && req) 
+    if (!((msg.oid == this._id && req)
        || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
       return;
     switch (aMessage.name) {
       case "Webapps:GetAll:Return:OK":
         Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
         break;
       case "Webapps:GetAll:Return:KO":
         Services.DOMRequest.fireError(req, "DENIED");
         break;
       case "Webapps:GetNotInstalled:Return:OK":
         Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
         break;
       case "Webapps:Install:Return:OK":
         if (this._oninstall) {
           let app = msg.app;
-          let event = new this._window.MozApplicationEvent("applicationinstall", 
+          let event = new this._window.MozApplicationEvent("applicationinstall",
                            { application : createApplicationObject(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
                                                                   app.installOrigin, app.installTime) });
           this._oninstall.handleEvent(event);
         }
         break;
       case "Webapps:Uninstall:Return:OK":
         if (this._onuninstall) {
-          let event = new this._window.MozApplicationEvent("applicationuninstall", 
+          let event = new this._window.MozApplicationEvent("applicationuninstall",
                            { application : createApplicationObject(this._window, msg.origin, null, null, null, null, 0) });
           this._onuninstall.handleEvent(event);
         }
         break;
     }
     this.removeRequest(msg.requestID);
   },
 
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -10,16 +10,17 @@ const Ci = Components.interfaces;
 const Cr = Components.results;
 
 let EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "DOMApplicationManifest"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
+Cu.import("resource://gre/modules/AppsUtils.jsm");
 
 const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
@@ -45,26 +46,26 @@ XPCOMUtils.defineLazyGetter(this, "msgmg
   // are in a different directory (currently the Firefox profile that installed
   // the webapp); otherwise, they're in the current profile.
   const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
 #endif
 
 let DOMApplicationRegistry = {
   appsFile: null,
   webapps: { },
+  children: [ ],
   allAppsLaunchable: false,
 
   init: function() {
     this.messages = ["Webapps:Install", "Webapps:Uninstall",
-                    "Webapps:GetSelf",
-                    "Webapps:GetInstalled", "Webapps:GetNotInstalled",
-                    "Webapps:Launch", "Webapps:GetAll",
-                    "Webapps:InstallPackage", "Webapps:GetBasePath",
-                    "WebApps:GetAppByManifestURL", "WebApps:GetAppLocalIdByManifestURL",
-                    "WebApps:GetAppByLocalId", "WebApps:GetManifestURLByLocalId"];
+                     "Webapps:GetSelf",
+                     "Webapps:GetInstalled", "Webapps:GetNotInstalled",
+                     "Webapps:Launch", "Webapps:GetAll",
+                     "Webapps:InstallPackage", "Webapps:GetBasePath",
+                     "Webapps:GetList"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
@@ -75,16 +76,21 @@ let DOMApplicationRegistry = {
         this.webapps = aData;
         for (let id in this.webapps) {
 #ifdef MOZ_SYS_MSG
           this._processManifestForId(id);
 #endif
           if (!this.webapps[id].localId) {
             this.webapps[id].localId = this._nextLocalId();
           }
+
+          // Default to a non privileged status.
+          if (this.webapps[id].appStatus === undefined) {
+            this.webapps[id].appStatus = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
+          }
         };
       }).bind(this));
     }
 
     try {
       let hosts = Services.prefs.getCharPref("dom.mozApps.whitelist");
       hosts.split(",").forEach(function(aHost) {
         Services.perms.add(Services.io.newURI(aHost, null, null),
@@ -245,28 +251,19 @@ let DOMApplicationRegistry = {
           ppmm.broadcastAsyncMessage("Webapps:GetAll:Return:KO", msg);
         break;
       case "Webapps:InstallPackage":
         this.installPackage(msg);
         break;
       case "Webapps:GetBasePath":
         return FileUtils.getFile(DIRECTORY_NAME, ["webapps"], true).path;
         break;
-      case "WebApps:GetAppByManifestURL":
-        return this.getAppByManifestURL(msg.url);
-        break;
-      case "WebApps:GetAppLocalIdByManifestURL":
-        return { id: this.getAppLocalIdByManifestURL(msg.url) };
-        break;
-      case "WebApps:GetAppByLocalId":
-        return this.getAppByLocalId(msg.id);
-        break;
-      case "WebApps:GetManifestURLByLocalId":
-        return this.getManifestURLByLocalId(msg.id);
-        break;
+      case "Webapps:GetList":
+        this.children.push(aMessage.target);
+        return this.webapps;
     }
   },
 
   _writeFile: function ss_writeFile(aFile, aData, aCallbak) {
     // Initialize the file output stream.
     let ostream = FileUtils.openSafeFileOutputStream(aFile);
 
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
@@ -277,30 +274,16 @@ let DOMApplicationRegistry = {
     // Asynchronously copy the data to the file.
     let istream = converter.convertToInputStream(aData);
     NetUtil.asyncCopy(istream, ostream, function(rc) {
       if (aCallbak)
         aCallbak();
     });
   },
 
-  // clones a app object, without the manifest
-  _cloneAppObject: function(aApp) {
-    let clone = {
-      installOrigin: aApp.installOrigin,
-      origin: aApp.origin,
-      receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
-      installTime: aApp.installTime,
-      manifestURL: aApp.manifestURL,
-      progress: aApp.progress || 0.0,
-      status: aApp.status || "installed"
-    };
-    return clone;
-  },
-
   denyInstall: function(aData) {
     let packageId = aData.app.packageId;
     if (packageId) {
       let dir = FileUtils.getDir("TmpD", ["webapps", packageId],
                                  true, true);
       try {
         dir.remove(true);
       } catch(e) {
@@ -326,51 +309,55 @@ let DOMApplicationRegistry = {
       localId = this._nextLocalId();
     }
 
     if (app.packageId) {
       // Override the origin with the correct id.
       app.origin = "app://" + id;
     }
 
-    let appObject = this._cloneAppObject(app);
+    let appObject = AppsUtils.cloneAppObject(app);
+    appObject.appStatus = app.appStatus || Ci.nsIPrincipal.APP_STATUS_INSTALLED;
     appObject.installTime = app.installTime = Date.now();
     let appNote = JSON.stringify(appObject);
     appNote.id = id;
 
     appObject.localId = localId;
 
     let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
     let manFile = dir.clone();
     manFile.append("manifest.webapp");
     this._writeFile(manFile, JSON.stringify(app.manifest), function() {
       // If this a packaged app, move the zip file from the temp directory,
       // and delete the temp directory.
       if (app.packageId) {
-        let appFile = FileUtils.getFile("TmpD", ["webapps", app.packageId, "application.zip"], 
+        let appFile = FileUtils.getFile("TmpD", ["webapps", app.packageId, "application.zip"],
                                         true, true);
         appFile.moveTo(dir, "application.zip");
-        let tmpDir = FileUtils.getDir("TmpD", ["webapps", app.packageId], 
+        let tmpDir = FileUtils.getDir("TmpD", ["webapps", app.packageId],
                                         true, true);
         try {
           tmpDir.remove(true);
         } catch(e) {
         }
       }
     });
     this.webapps[id] = appObject;
 
     appObject.status = "installed";
-    
+
     let manifest = new DOMApplicationManifest(app.manifest, app.origin);
 
     if (!aFromSync)
       this._saveApps((function() {
         ppmm.broadcastAsyncMessage("Webapps:Install:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
+        this.children.forEach(function(aMsgMgr) {
+          aMsgMgr.broadcastAsyncMessage("Webapps:AddApp", { id: id, app: appObject });
+        });
       }).bind(this));
 
 #ifdef MOZ_SYS_MSG
     this._registerSystemMessages(id, app);
 #endif
 
     // if the manifest has an appcache_path property, use it to populate the appcache
     if (manifest.appcache_path) {
@@ -492,16 +479,57 @@ let DOMApplicationRegistry = {
         dir.remove(true);
       } catch (e) { }
       ppmm.broadcastAsyncMessage("Webapps:Install:Return:KO",
                             { oid: aData.oid,
                               requestID: aData.requestID,
                               error: aError });
     }
 
+    function getInferedStatus() {
+      // XXX Update once we have digital signatures (bug 772365)
+      return Ci.nsIPrincipal.APP_STATUS_INSTALLED;
+    }
+
+    function getAppManifestStatus(aManifest) {
+      let type = aManifest.type || "web";
+      let manifestStatus = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
+
+      switch(type) {
+        case "web":
+          manifestStatus = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
+          break;
+        case "privileged":
+          manifestStatus = Ci.nsIPrincipal.APP_STATUS_PRIVILEGED;
+          break
+        case "certified":
+          manifestStatus = Ci.nsIPrincipal.APP_STATUS_CERTIFIED;
+          break;
+      }
+
+      return manifestStatus;
+    }
+
+    function getAppStatus(aManifest) {
+      let manifestStatus = getAppManifestStatus(aManifest);
+      let inferedStatus = getInferedStatus();
+
+      return (Services.prefs.getBoolPref("dom.mozApps.dev_mode") ? manifestStatus
+                                                                : inferedStatus);
+    }
+    // Returns true if the privilege level from the manifest
+    // is lower or equal to the one we infered for the app.
+    function checkAppStatus(aManifest) {
+      if (Services.prefs.getBoolPref("dom.mozApps.dev_mode")) {
+        return true;
+      }
+
+      return (getAppManifestStatus(aManifest) <= getInferedStatus());
+    }
+
     NetUtil.asyncFetch(aData.url, function(aInput, aResult, aRequest) {
       if (!Components.isSuccessCode(aResult)) {
         // We failed to fetch the zip.
         cleanup("NETWORK_ERROR");
         return;
       }
       // Copy the zip on disk.
       let zipFile = FileUtils.getFile("TmpD",
@@ -537,41 +565,46 @@ let DOMApplicationRegistry = {
           if (!zipReader.hasEntry("manifest.webapp")) {
             throw "No manifest.webapp found.";
           }
 
           let istream = zipReader.getInputStream("manifest.webapp");
           msg.app.manifest = JSON.parse(NetUtil.readInputStreamToString(istream,
                                         istream.available()) || "");
           if (!checkManifest(msg.app.manifest)) {
-            throw "Invalid manifest";
+            throw "INVALID_MANIFEST";
           }
 
+          if (!checkAppStatus(msg.app.manifest)) {
+            throw "INVALID_SECURITY_LEVEL";
+          }
+
+          msg.appStatus = getAppStatus(msg.app.manifest);
           Services.obs.notifyObservers(this, "webapps-ask-install",
                                              JSON.stringify(msg));
         } catch (e) {
           // XXX we may need new error messages.
-          cleanup("INVALID_MANIFEST");
+          cleanup(e);
         } finally {
           zipReader.close();
         }
       });
     });
   },
 
   uninstall: function(aData) {
     let found = false;
     for (let id in this.webapps) {
       let app = this.webapps[id];
       if (app.origin != aData.origin) {
         continue;
       }
 
       found = true;
-      let appNote = JSON.stringify(this._cloneAppObject(app));
+      let appNote = JSON.stringify(AppsUtils.cloneAppObject(app));
       appNote.id = id;
 
       this._readManifests([{ id: id }], (function unregisterManifest(aResult) {
 #ifdef MOZ_SYS_MSG
         this._unregisterActivities(aResult[0].manifest, app);
 #endif
       }).bind(this));
 
@@ -580,31 +613,34 @@ let DOMApplicationRegistry = {
         dir.remove(true);
       } catch (e) {}
 
       delete this.webapps[id];
 
       this._saveApps((function() {
         ppmm.broadcastAsyncMessage("Webapps:Uninstall:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-uninstall", appNote);
+        this.children.forEach(function(aMsgMgr) {
+          aMsgMgr.broadcastAsyncMessage("Webapps:RemoveApp", { id: id });
+        });
       }).bind(this));
     }
 
     if (!found) {
       ppmm.broadcastAsyncMessage("Webapps:Uninstall:Return:KO", aData);
     }
   },
 
   getSelf: function(aData) {
     aData.apps = [];
     let tmp = [];
     let id = this._appId(aData.origin);
 
     if (id && this._isLaunchable(this.webapps[id].origin)) {
-      let app = this._cloneAppObject(this.webapps[id]);
+      let app = AppsUtils.cloneAppObject(this.webapps[id]);
       aData.apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       ppmm.broadcastAsyncMessage("Webapps:GetSelf:Return:OK", aData);
@@ -613,17 +649,17 @@ let DOMApplicationRegistry = {
 
   getInstalled: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       if (this.webapps[id].installOrigin == aData.origin &&
           this._isLaunchable(this.webapps[id].origin)) {
-        aData.apps.push(this._cloneAppObject(this.webapps[id]));
+        aData.apps.push(AppsUtils.cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       ppmm.broadcastAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
@@ -631,34 +667,34 @@ let DOMApplicationRegistry = {
   },
 
   getNotInstalled: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       if (!this._isLaunchable(this.webapps[id].origin)) {
-        aData.apps.push(this._cloneAppObject(this.webapps[id]));
+        aData.apps.push(AppsUtils.cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       ppmm.broadcastAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
     }).bind(this));
   },
 
   getAll: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
-      let app = this._cloneAppObject(this.webapps[id]);
+      let app = AppsUtils.cloneAppObject(this.webapps[id]);
       if (!this._isLaunchable(app.origin))
         continue;
 
       aData.apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
@@ -687,88 +723,40 @@ let DOMApplicationRegistry = {
   itemExists: function(aId) {
     return !!this.webapps[aId];
   },
 
   getAppById: function(aId) {
     if (!this.webapps[aId])
       return null;
 
-    let app = this._cloneAppObject(this.webapps[aId]);
+    let app = AppsUtils.cloneAppObject(this.webapps[aId]);
     return app;
   },
 
   getAppByManifestURL: function(aManifestURL) {
-    // This could be O(1) if |webapps| was a dictionary indexed on manifestURL
-    // which should be the unique app identifier.
-    // It's currently O(n).
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.manifestURL == aManifestURL) {
-        let res = this._cloneAppObject(app);
-        res.hasPermission = function(permission) {
-          let localId = DOMApplicationRegistry.getAppLocalIdByManifestURL(
-            this.manifestURL);
-          let uri = Services.io.newURI(this.manifestURL, null, null);
-          let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-                       .getService(Ci.nsIScriptSecurityManager);
-          // XXX for the purposes of permissions checking, this helper
-          // should always be called on !isBrowser frames, so we
-          // assume false here.
-          let principal = secMan.getAppCodebasePrincipal(uri, localId,
-                                                         /*mozbrowser*/false);
-          let perm = Services.perms.testExactPermissionFromPrincipal(principal,
-                                                                     permission);
-          return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
-        };
-        res.QueryInterface = XPCOMUtils.generateQI([Ci.mozIDOMApplication,
-                                                    Ci.mozIApplication]);
-        return res;
-      }
-    }
-
-    return null;
+    return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
   },
 
   getAppByLocalId: function(aLocalId) {
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.localId == aLocalId) {
-        return this._cloneAppObject(app);
-      }
-    }
-
-    return null;
+    return AppsUtils.getAppByLocalId(this.webapps, aLocalId);
   },
 
   getManifestURLByLocalId: function(aLocalId) {
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.localId == aLocalId) {
-        return app.manifestURL;
-      }
-    }
-
-    return null;
+    return AppsUtils.getManifestURLByLocalId(this.webapps, aLocalId);
   },
 
   getAppLocalIdByManifestURL: function(aManifestURL) {
-    for (let id in this.webapps) {
-      if (this.webapps[id].manifestURL == aManifestURL) {
-        return this.webapps[id].localId;
-      }
-    }
-
-    return Ci.nsIScriptSecurityManager.NO_APP_ID;
+    return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
   },
 
   getAllWithoutManifests: function(aCallback) {
     let result = {};
     for (let id in this.webapps) {
-      let app = this._cloneAppObject(this.webapps[id]);
+      let app = AppsUtils.cloneAppObject(this.webapps[id]);
       result[id] = app;
     }
     aCallback(result);
   },
 
   updateApps: function(aRecords, aCallback) {
     for (let i = 0; i < aRecords.length; i++) {
       let record = aRecords[i];
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -31,17 +31,19 @@
 #include "nsIPowerManagerService.h"
 #include "SmsManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "Connection.h"
+#ifdef MOZ_B2G_RIL
 #include "MobileConnection.h"
+#endif
 #include "nsIIdleObserver.h"
 #include "nsIPermissionManager.h"
 #include "nsNetUtil.h"
 #include "nsIHttpChannel.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "MediaManager.h"
 #endif
@@ -111,16 +113,19 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
 #ifdef MOZ_MEDIA_NAVIGATOR
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorUserMedia)
 #endif
 #ifdef MOZ_B2G_RIL
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorNetwork)
+#ifdef MOZ_B2G_RIL
+  NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorMobileConnection)
+#endif
 #ifdef MOZ_B2G_BT
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorBluetooth)
 #endif
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorCamera)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorSystemMessages)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
 NS_INTERFACE_MAP_END
 
@@ -173,20 +178,22 @@ Navigator::Invalidate()
   }
 #endif
 
   if (mConnection) {
     mConnection->Shutdown();
     mConnection = nullptr;
   }
 
+#ifdef MOZ_B2G_RIL
   if (mMobileConnection) {
     mMobileConnection->Shutdown();
     mMobileConnection = nullptr;
   }
+#endif
 
 #ifdef MOZ_B2G_BT
   if (mBluetooth) {
     mBluetooth = nullptr;
   }
 #endif
 
   mCameraManager = nullptr;
@@ -1180,16 +1187,20 @@ Navigator::GetMozConnection(nsIDOMMozCon
     mConnection = new network::Connection();
     mConnection->Init(window);
   }
 
   NS_ADDREF(*aConnection = mConnection);
   return NS_OK;
 }
 
+#ifdef MOZ_B2G_RIL
+//*****************************************************************************
+//    Navigator::nsINavigatorMobileConnection
+//*****************************************************************************
 NS_IMETHODIMP
 Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection)
 {
   *aMobileConnection = nullptr;
 
   if (!mMobileConnection) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window, NS_OK);
@@ -1210,16 +1221,17 @@ Navigator::GetMozMobileConnection(nsIDOM
 
     mMobileConnection = new network::MobileConnection();
     mMobileConnection->Init(window);
   }
 
   NS_ADDREF(*aMobileConnection = mMobileConnection);
   return NS_OK;
 }
+#endif // MOZ_B2G_RIL
 
 #ifdef MOZ_B2G_BT
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorBluetooth
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozBluetooth(nsIDOMBluetoothManager** aBluetooth)
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -10,16 +10,19 @@
 #include "nsIDOMNavigator.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "nsIDOMNavigatorDeviceStorage.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMClientInformation.h"
 #include "nsINavigatorBattery.h"
 #include "nsIDOMNavigatorSms.h"
 #include "nsIDOMNavigatorNetwork.h"
+#ifdef MOZ_B2G_RIL
+#include "nsINavigatorMobileConnection.h"
+#endif
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 #include "DeviceStorage.h"
 
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsGeolocation;
 class nsDesktopNotificationCenter;
@@ -57,17 +60,19 @@ class BatteryManager;
 } // namespace battery
 
 namespace sms {
 class SmsManager;
 } // namespace sms
 
 namespace network {
 class Connection;
+#ifdef MOZ_B2G_RIL
 class MobileConnection;
+#endif
 } // namespace Connection;
 
 namespace power {
 class PowerManager;
 } // namespace power
 
 class Navigator : public nsIDOMNavigator
                 , public nsIDOMClientInformation
@@ -78,16 +83,19 @@ class Navigator : public nsIDOMNavigator
                 , public nsIDOMMozNavigatorSms
 #ifdef MOZ_MEDIA_NAVIGATOR
                 , public nsIDOMNavigatorUserMedia
 #endif
 #ifdef MOZ_B2G_RIL
                 , public nsIDOMNavigatorTelephony
 #endif
                 , public nsIDOMMozNavigatorNetwork
+#ifdef MOZ_B2G_RIL
+                , public nsIMozNavigatorMobileConnection
+#endif
 #ifdef MOZ_B2G_BT
                 , public nsIDOMNavigatorBluetooth
 #endif
                 , public nsIDOMNavigatorCamera
                 , public nsIDOMNavigatorSystemMessages
 {
 public:
   Navigator(nsPIDOMWindow *aInnerWindow);
@@ -103,16 +111,19 @@ public:
   NS_DECL_NSIDOMMOZNAVIGATORSMS
 #ifdef MOZ_MEDIA_NAVIGATOR
   NS_DECL_NSIDOMNAVIGATORUSERMEDIA
 #endif
 #ifdef MOZ_B2G_RIL
   NS_DECL_NSIDOMNAVIGATORTELEPHONY
 #endif
   NS_DECL_NSIDOMMOZNAVIGATORNETWORK
+#ifdef MOZ_B2G_RIL
+  NS_DECL_NSIMOZNAVIGATORMOBILECONNECTION
+#endif
 
 #ifdef MOZ_B2G_BT
   NS_DECL_NSIDOMNAVIGATORBLUETOOTH
 #endif
   NS_DECL_NSIDOMNAVIGATORSYSTEMMESSAGES
 
   static void Init();
 
@@ -151,17 +162,19 @@ private:
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
   nsCOMPtr<nsIDOMMozVoicemail> mVoicemail;
 #endif
   nsRefPtr<network::Connection> mConnection;
+#ifdef MOZ_B2G_RIL
   nsRefPtr<network::MobileConnection> mMobileConnection;
+#endif
 #ifdef MOZ_B2G_BT
   nsCOMPtr<nsIDOMBluetoothManager> mBluetooth;
 #endif
   nsRefPtr<nsDOMCameraManager> mCameraManager;
   nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
   nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
   nsWeakPtr mWindow;
 };
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -496,26 +496,30 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "nsIDOMWakeLock.h"
 #include "nsIDOMSmsManager.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsIDOMSmsEvent.h"
 #include "nsIDOMSmsRequest.h"
 #include "nsIDOMSmsFilter.h"
 #include "nsIDOMSmsCursor.h"
 #include "nsIDOMConnection.h"
+#ifdef MOZ_B2G_RIL
 #include "nsIDOMMobileConnection.h"
+#endif
 #include "USSDReceivedEvent.h"
 #include "mozilla/dom/network/Utils.h"
 
 #ifdef MOZ_B2G_RIL
 #include "Telephony.h"
 #include "TelephonyCall.h"
 #include "CallEvent.h"
 #include "nsIDOMVoicemail.h"
 #include "nsIDOMVoicemailEvent.h"
+#include "nsIDOMIccManager.h"
+#include "StkCommandEvent.h"
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "BluetoothManager.h"
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothPropertyEvent.h"
 #endif
@@ -1485,18 +1489,20 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsCursor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozConnection, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
+#ifdef MOZ_B2G_RIL
   NS_DEFINE_CLASSINFO_DATA(MozMobileConnection, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+#endif
 
   NS_DEFINE_CLASSINFO_DATA(USSDReceivedEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceStyleDecl, nsCSSStyleDeclSH,
                            ARRAY_SCRIPTABLE_FLAGS)
@@ -1671,16 +1677,20 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CallEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozVoicemail, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozVoicemailEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(MozIccManager, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(MozStkCommandEvent, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_B2G_BT
   NS_DEFINE_CLASSINFO_DATA(BluetoothManager, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)  
   NS_DEFINE_CLASSINFO_DATA(BluetoothDevice, nsEventTargetSH,
@@ -2481,16 +2491,19 @@ nsDOMClassInfo::Init()
 #ifdef MOZ_MEDIA_NAVIGATOR
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorUserMedia)
 #endif
 #ifdef MOZ_B2G_RIL
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorTelephony)
 #endif
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMMozNavigatorNetwork,
                                         network::IsAPIEnabled())
+#ifdef MOZ_B2G_RIL
+    DOM_CLASSINFO_MAP_ENTRY(nsIMozNavigatorMobileConnection)
+#endif
 #ifdef MOZ_B2G_BT
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorBluetooth)
 #endif
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorCamera)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorSystemMessages)
 
   DOM_CLASSINFO_MAP_END
 
@@ -4123,20 +4136,22 @@ nsDOMClassInfo::Init()
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsCursor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozConnection, nsIDOMMozConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
+#ifdef MOZ_B2G_RIL
   DOM_CLASSINFO_MAP_BEGIN(MozMobileConnection, nsIDOMMozMobileConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileConnection)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
+#endif
 
   DOM_CLASSINFO_MAP_BEGIN(USSDReceivedEvent, nsIDOMUSSDReceivedEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMUSSDReceivedEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
  
   DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
@@ -4472,16 +4487,27 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozVoicemail)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozVoicemailEvent, nsIDOMMozVoicemailEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozVoicemailEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(MozIccManager, nsIDOMMozIccManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozIccManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(MozStkCommandEvent, nsIDOMMozStkCommandEvent)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozStkCommandEvent)
+    DOM_CLASSINFO_EVENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+
 #endif
 
 #ifdef MOZ_B2G_BT
   DOM_CLASSINFO_MAP_BEGIN(BluetoothManager, nsIDOMBluetoothManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothManager)
   DOM_CLASSINFO_MAP_END  
 
   DOM_CLASSINFO_MAP_BEGIN(BluetoothAdapter, nsIDOMBluetoothAdapter)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -402,17 +402,19 @@ DOMCI_CLASS(MozWakeLock)
 DOMCI_CLASS(MozSmsManager)
 DOMCI_CLASS(MozSmsMessage)
 DOMCI_CLASS(MozSmsEvent)
 DOMCI_CLASS(MozSmsRequest)
 DOMCI_CLASS(MozSmsFilter)
 DOMCI_CLASS(MozSmsCursor)
 
 DOMCI_CLASS(MozConnection)
+#ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozMobileConnection)
+#endif
 
 DOMCI_CLASS(USSDReceivedEvent)
 
 // @font-face in CSS
 DOMCI_CLASS(CSSFontFaceRule)
 DOMCI_CLASS(CSSFontFaceStyleDecl)
 
 #if defined(MOZ_MEDIA)
@@ -514,16 +516,18 @@ DOMCI_CLASS(MutationRecord)
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozWifiStatusChangeEvent)
 DOMCI_CLASS(MozWifiConnectionInfoEvent)
 DOMCI_CLASS(Telephony)
 DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(CallEvent)
 DOMCI_CLASS(MozVoicemail)
 DOMCI_CLASS(MozVoicemailEvent)
+DOMCI_CLASS(MozIccManager)
+DOMCI_CLASS(MozStkCommandEvent)
 #endif
 
 #ifdef MOZ_B2G_BT
 DOMCI_CLASS(BluetoothManager)
 DOMCI_CLASS(BluetoothAdapter)
 DOMCI_CLASS(BluetoothDevice)
 DOMCI_CLASS(BluetoothPropertyEvent)
 #endif
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -636,20 +636,17 @@ nsDOMWindowUtils::SendWheelEvent(float a
   nsPresContext* presContext = GetPresContext();
   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
   wheelEvent.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
 
   nsEventStatus status;
   nsresult rv = widget->DispatchEvent(&wheelEvent, status);
   NS_ENSURE_SUCCESS(rv, rv);
-  // ESM must not return negative values for overflow.
-  NS_ENSURE_TRUE(wheelEvent.overflowDeltaX >= 0.0, NS_ERROR_FAILURE);
-  NS_ENSURE_TRUE(wheelEvent.overflowDeltaY >= 0.0, NS_ERROR_FAILURE);
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendTouchEvent(const nsAString& aType,
                                  uint32_t *aIdentifiers,
                                  int32_t *aXs,
                                  int32_t *aYs,
                                  uint32_t *aRxs,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2513,17 +2513,17 @@ nsGlobalWindow::PreHandleEvent(nsEventCh
 
 bool
 nsGlobalWindow::DialogsAreBlocked(bool *aBeingAbused)
 {
   *aBeingAbused = false;
 
   nsGlobalWindow *topWindow = GetScriptableTop();
   if (!topWindow) {
-    NS_ERROR("DialogsAreBlocked() called without a top window?");
+    NS_ASSERTION(!mDocShell, "DialogsAreBlocked() called without a top window?");
     return true;
   }
 
   topWindow = topWindow->GetCurrentInnerWindowInternal();
   if (!topWindow) {
     return true;
   }
 
@@ -7647,19 +7647,21 @@ nsGlobalWindow::ActivateOrDeactivate(boo
   } else {
     // This is a workaround for the following problem:
     // When a window with an open sheet loses focus, only the sheet window
     // receives the NS_DEACTIVATE event. However, it's not the sheet that
     // should lose the active styling, but the containing top level window.
 
     // widgetListener should be a nsXULWindow
     nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
-    nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
-    nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
-    topLevelWindow = do_GetInterface(req);
+    if (listener) {
+      nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
+      nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
+      topLevelWindow = do_GetInterface(req);
+    }
   }
   if (topLevelWindow) {
     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
     piWin->SetActive(aActivate);
   }
 }
 
 static bool
@@ -11069,36 +11071,36 @@ nsGlobalWindow::SetHasAudioAvailableEven
   if (mDoc) {
     mDoc->NotifyAudioAvailableListener();
   }
 }
 
 #define EVENT(name_, id_, type_, struct_)                                    \
   NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx,                  \
                                              jsval *vp) {                    \
-    nsEventListenerManager *elm = GetListenerManager(false);              \
+    nsEventListenerManager *elm = GetListenerManager(false);                 \
     if (elm) {                                                               \
-      elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
+      elm->GetEventHandler(nsGkAtoms::on##name_, vp);                        \
     } else {                                                                 \
       *vp = JSVAL_NULL;                                                      \
     }                                                                        \
     return NS_OK;                                                            \
   }                                                                          \
   NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx,                  \
                                              const jsval &v) {               \
-    nsEventListenerManager *elm = GetListenerManager(true);               \
+    nsEventListenerManager *elm = GetListenerManager(true);                  \
     if (!elm) {                                                              \
       return NS_ERROR_OUT_OF_MEMORY;                                         \
     }                                                                        \
                                                                              \
     JSObject *obj = mJSObject;                                               \
     if (!obj) {                                                              \
       return NS_ERROR_UNEXPECTED;                                            \
     }                                                                        \
-    return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
+    return elm->SetEventHandlerToJsval(nsGkAtoms::on##name_, cx, obj, v);    \
   }
 #define WINDOW_ONLY_EVENT EVENT
 #define TOUCH_EVENT EVENT
 #include "nsEventNameList.h"
 #undef TOUCH_EVENT
 #undef WINDOW_ONLY_EVENT
 #undef EVENT
 
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -110,16 +110,18 @@ BluetoothDevice::SetPropertyByValue(cons
     if (!bs) {
       NS_WARNING("BluetoothService not available!");
       return;
     }
     // We can't actually set up our path until we know our address
     bs->GetDevicePath(mAdapterPath, mAddress, mPath);
   } else if (name.EqualsLiteral("Class")) {
     mClass = value.get_uint32_t();
+  } else if (name.EqualsLiteral("Icon")) {
+    mIcon = value.get_nsString();
   } else if (name.EqualsLiteral("Connected")) {
     mConnected = value.get_bool();
   } else if (name.EqualsLiteral("Paired")) {
     mPaired = value.get_bool();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
@@ -217,16 +219,23 @@ BluetoothDevice::GetAddress(nsAString& a
 NS_IMETHODIMP
 BluetoothDevice::GetName(nsAString& aName)
 {
   aName = mName;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+BluetoothDevice::GetIcon(nsAString& aIcon)
+{
+  aIcon = mIcon;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 BluetoothDevice::GetDeviceClass(uint32_t* aClass)
 {
   *aClass = mClass;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothDevice::GetPaired(bool* aPaired)
--- a/dom/bluetooth/BluetoothDevice.h
+++ b/dom/bluetooth/BluetoothDevice.h
@@ -63,16 +63,17 @@ private:
   ~BluetoothDevice();
   void Root();
   
   JSObject* mJsUuids;
 
   nsString mAdapterPath;
   nsString mAddress;
   nsString mName;
+  nsString mIcon;
   uint32_t mClass;
   bool mConnected;
   bool mPaired;
   bool mIsRooted;
   nsTArray<nsString> mUuids;
 
   NS_DECL_EVENT_HANDLER(propertychanged)
   NS_DECL_EVENT_HANDLER(connected)
--- a/dom/bluetooth/BluetoothManager.cpp
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -8,42 +8,48 @@
 #include "BluetoothManager.h"
 #include "BluetoothCommon.h"
 #include "BluetoothAdapter.h"
 #include "BluetoothService.h"
 #include "BluetoothTypes.h"
 #include "BluetoothReplyRunnable.h"
 
 #include "nsContentUtils.h"
-#include "nsIDOMDOMRequest.h"
-#include "nsIPermissionManager.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsIDOMDOMRequest.h"
+#include "nsIJSContextStack.h"
+#include "nsIObserverService.h"
+#include "nsIPermissionManager.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "mozilla/LazyIdleThread.h"
+#include "mozilla/Services.h"
 #include "mozilla/Util.h"
 #include "nsIDOMDOMRequest.h"
 
 using namespace mozilla;
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothManager, BluetoothManager)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager,
                                                   nsDOMEventTargetHelper)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(disabled)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothManager,
                                                 nsDOMEventTargetHelper)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(disabled)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothManager)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(BluetoothManager, nsDOMEventTargetHelper)
@@ -96,125 +102,202 @@ public:
     BluetoothReplyRunnable::ReleaseMembers();
     mManagerPtr = nullptr;
   }
   
 private:
   nsRefPtr<BluetoothManager> mManagerPtr;
 };
 
-class ToggleBtResultTask : public BluetoothReplyRunnable
+class ToggleBtResultTask : public nsRunnable
 {
 public:
-  ToggleBtResultTask(BluetoothManager* aManager,
-                     nsIDOMDOMRequest* aReq,
-                     bool aEnabled)
-    : BluetoothReplyRunnable(aReq),
-      mManagerPtr(aManager),
+  ToggleBtResultTask(BluetoothManager* aManager, bool aEnabled)
+    : mManagerPtr(aManager),
       mEnabled(aEnabled)
   {
   }
 
-  ~ToggleBtResultTask()
-  {
-  }
-  
-  bool
-  ParseSuccessfulReply(jsval* aValue)
+  NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
-    *aValue = JSVAL_VOID;
-    mManagerPtr->SetEnabledInternal(mEnabled);
-    return true;
-  }
 
-  void
-  ReleaseMembers()
-  {
-    BluetoothReplyRunnable::ReleaseMembers();
+    mManagerPtr->SetEnabledInternal(mEnabled);
+    mManagerPtr->FireEnabledDisabledEvent();
+
     // mManagerPtr must be null before returning to prevent the background
     // thread from racing to release it during the destruction of this runnable.
     mManagerPtr = nullptr;
+
+    return NS_OK;
   }
-  
+
 private:
   nsRefPtr<BluetoothManager> mManagerPtr;
   bool mEnabled;
 };
 
+nsresult
+BluetoothManager::FireEnabledDisabledEvent()
+{
+  nsString eventName;
+
+  if (mEnabled) {
+    eventName.AssignLiteral("enabled");
+  } else {
+    eventName.AssignLiteral("disabled");
+  }
+
+  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nullptr, nullptr);
+  nsresult rv = event->InitEvent(eventName, false, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = event->SetTrusted(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool dummy;
+  rv = DispatchEvent(event, &dummy);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) :
   BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER),
   mEnabled(false)
 {
   BindToOwner(aWindow);
   mPath.AssignLiteral("/");
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  obs->AddObserver(this, "mozsettings-changed", false);
 }
 
 BluetoothManager::~BluetoothManager()
 {
   BluetoothService* bs = BluetoothService::Get();
   // We can be null on shutdown, where this might happen
   if (bs) {
     if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
       NS_WARNING("Failed to unregister object with observer!");
     }
   }
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  obs->RemoveObserver(this, "mozsettings-changed");
+}
+
+nsresult
+BluetoothManager::HandleMozsettingChanged(const PRUnichar* aData)
+{
+  // The string that we're interested in will be a JSON string that looks like:
+  //  {"key":"bluetooth.enabled","value":true}
+  nsresult rv;
+
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  if (NS_FAILED(rv)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  JSContext *cx = sc->GetNativeContext();
+  if (!cx) {
+    return NS_OK;
+  }
+
+  // In the following [if] blocks, NS_OK will be returned even if JS_* functions
+  // return false. That's because this function gets called whenever mozSettings
+  // changes, so that we'll receive signals we're not interested in and it would
+  // be one of the reasons for making JS_* functions return false.
+  nsDependentString dataStr(aData);
+  JS::Value val;
+  if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val)) {
+    return NS_OK;
+  }
+
+  if (!val.isObject()) {
+    return NS_OK;
+  }
+
+  JSObject &obj(val.toObject());
+  JS::Value key;
+  if (!JS_GetProperty(cx, &obj, "key", &key)) {
+    return NS_OK;
+  }
+
+  if (!key.isString()) {
+    return NS_OK;
+  }
+
+  JSBool match;
+  if (!JS_StringEqualsAscii(cx, key.toString(), "bluetooth.enabled", &match)) {
+    return NS_OK;
+  }
+
+  if (!match) {
+    return NS_OK;
+  }
+
+  JS::Value value;
+  if (!JS_GetProperty(cx, &obj, "value", &value)) {
+    return NS_OK;
+  }
+
+  if (!value.isBoolean()) {
+    return NS_OK;
+  }
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  bool enabled = value.toBoolean();
+  nsCOMPtr<nsIRunnable> resultTask = new ToggleBtResultTask(this, enabled);
+
+  if (enabled) {
+    if (NS_FAILED(bs->Start(resultTask))) {
+      return NS_ERROR_FAILURE;
+    }
+  } else {
+    if (NS_FAILED(bs->Stop(resultTask))) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BluetoothManager::Observe(nsISupports* aSubject,
+                          const char* aTopic,
+                          const PRUnichar* aData)
+{
+  nsresult rv = NS_OK;
+
+  if (!strcmp("mozsettings-changed", aTopic)) {
+    rv = HandleMozsettingChanged(aData);
+  }
+
+  return rv;
 }
 
 void
 BluetoothManager::SetPropertyByValue(const BluetoothNamedValue& aValue)
 {
 #ifdef DEBUG
     const nsString& name = aValue.name();
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling manager property: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(name));
     NS_WARNING(warningMsg.get());
 #endif
 }
 
 NS_IMETHODIMP
-BluetoothManager::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
-{
-  BluetoothService* bs = BluetoothService::Get();
-  if (!bs) {
-    NS_WARNING("BluetoothService not available!");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
-  if (!rs) {
-    NS_WARNING("No DOMRequest Service!");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDOMDOMRequest> request;
-  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Can't create DOM request!");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsRefPtr<BluetoothReplyRunnable> results = new ToggleBtResultTask(this, request, aEnabled);
-  if (aEnabled) {
-    if (NS_FAILED(bs->Start(results))) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-  else {
-    if (NS_FAILED(bs->Stop(results))) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
-  request.forget(aDomRequest);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 BluetoothManager::GetEnabled(bool* aEnabled)
 {
   *aEnabled = mEnabled;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothManager::GetDefaultAdapter(nsIDOMDOMRequest** aAdapter)
@@ -313,8 +396,11 @@ BluetoothManager::Notify(const Bluetooth
 {
 #ifdef DEBUG
   nsCString warningMsg;
   warningMsg.AssignLiteral("Not handling manager signal: ");
   warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
   NS_WARNING(warningMsg.get());
 #endif
 }
+
+NS_IMPL_EVENT_HANDLER(BluetoothManager, enabled)
+NS_IMPL_EVENT_HANDLER(BluetoothManager, disabled)
--- a/dom/bluetooth/BluetoothManager.h
+++ b/dom/bluetooth/BluetoothManager.h
@@ -6,50 +6,58 @@
 
 #ifndef mozilla_dom_bluetooth_bluetoothmanager_h__
 #define mozilla_dom_bluetooth_bluetoothmanager_h__
 
 #include "BluetoothCommon.h"
 #include "BluetoothPropertyContainer.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothManager.h"
+#include "nsIEventTarget.h"
+#include "nsIObserver.h"
 #include "mozilla/Observer.h"
-#include "nsIEventTarget.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothNamedValue;
 
 class BluetoothManager : public nsDOMEventTargetHelper
                        , public nsIDOMBluetoothManager
                        , public BluetoothSignalObserver
                        , public BluetoothPropertyContainer
+                       , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMBLUETOOTHMANAGER
+  NS_DECL_NSIOBSERVER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothManager,
                                            nsDOMEventTargetHelper)
 
 
   inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
 
   static already_AddRefed<BluetoothManager>
   Create(nsPIDOMWindow* aWindow);
   void Notify(const BluetoothSignal& aData);
   virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);
+  nsresult FireEnabledDisabledEvent();
 private:
   BluetoothManager(nsPIDOMWindow* aWindow);
   ~BluetoothManager();
+
+  nsresult HandleMozsettingChanged(const PRUnichar* aData);
+
   bool mEnabled;
 
   NS_DECL_EVENT_HANDLER(enabled)
+  NS_DECL_EVENT_HANDLER(disabled)
 };
 
 END_BLUETOOTH_NAMESPACE
 
 nsresult NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
                                 nsIDOMBluetoothManager** aBluetoothManager);
 
 #endif
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -25,18 +25,17 @@ USING_BLUETOOTH_NAMESPACE
 static nsRefPtr<BluetoothService> gBluetoothService;
 static bool gInShutdown = false;
 
 NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
 
 class ToggleBtAck : public nsRunnable
 {
 public:
-  ToggleBtAck(bool aEnabled) :
-    mEnabled(aEnabled)
+  ToggleBtAck(bool aEnabled) : mEnabled(aEnabled)
   {
   }
   
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!mEnabled || gInShutdown) {
@@ -56,17 +55,17 @@ public:
 
   bool mEnabled;
 };
 
 class ToggleBtTask : public nsRunnable
 {
 public:
   ToggleBtTask(bool aEnabled,
-               BluetoothReplyRunnable* aRunnable)
+               nsIRunnable* aRunnable)
     : mEnabled(aEnabled),
       mRunnable(aRunnable)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   NS_IMETHOD Run() 
   {
@@ -90,37 +89,27 @@ public:
     nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck(mEnabled);
     if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     
     if (!mRunnable) {
       return NS_OK;
     }
-    
-    // Reply will be deleted by the runnable after running on main thread
-    BluetoothReply* reply;
-    if (!replyError.IsEmpty()) {
-      reply = new BluetoothReply(BluetoothReplyError(replyError));
-    }
-    else {
-      reply = new BluetoothReply(BluetoothReplySuccess());
-    }
-    mRunnable->SetReply(reply);
-      
+
     if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     
     return NS_OK;
   }
 
 private:
   bool mEnabled;
-  nsRefPtr<BluetoothReplyRunnable> mRunnable;
+  nsCOMPtr<nsIRunnable> mRunnable;
 };
 
 nsresult
 BluetoothService::RegisterBluetoothSignalHandler(const nsAString& aNodeName,
                                                  BluetoothSignalObserver* aHandler)
 {
   MOZ_ASSERT(NS_IsMainThread());
   BluetoothSignalObserverList* ol;
@@ -158,18 +147,17 @@ BluetoothService::DistributeSignal(const
   if (!mBluetoothSignalObserverTable.Get(signal.path(), &ol)) {
     return NS_OK;
   }
   ol->Broadcast(signal);
   return NS_OK;
 }
 
 nsresult
-BluetoothService::StartStopBluetooth(BluetoothReplyRunnable* aResultRunnable,
-                                     bool aStart)
+BluetoothService::StartStopBluetooth(nsIRunnable* aResultRunnable, bool aStart)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // If we're shutting down, bail early.
   if (gInShutdown && aStart) {
     NS_ERROR("Start called while in shutdown!");
     return NS_ERROR_FAILURE;
   }
@@ -182,23 +170,23 @@ BluetoothService::StartStopBluetooth(Blu
   if (NS_FAILED(mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 nsresult
-BluetoothService::Start(BluetoothReplyRunnable* aResultRunnable)
+BluetoothService::Start(nsIRunnable* aResultRunnable)
 {
   return StartStopBluetooth(aResultRunnable, true);
 }
 
 nsresult
-BluetoothService::Stop(BluetoothReplyRunnable* aResultRunnable)
+BluetoothService::Stop(nsIRunnable* aResultRunnable)
 {
   return StartStopBluetooth(aResultRunnable, false);
 }
 
 // static
 BluetoothService*
 BluetoothService::Get()
 {
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetootheventservice_h__
 #define mozilla_dom_bluetooth_bluetootheventservice_h__
 
 #include "nsThreadUtils.h"
 #include "nsClassHashtable.h"
 #include "nsIObserver.h"
+#include "nsIRunnable.h"
 #include "BluetoothCommon.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSignal;
 class BluetoothReplyRunnable;
 class BluetoothNamedValue;
 
@@ -67,32 +68,32 @@ public:
    *
    * @param aResultRunnable Runnable object to execute after bluetooth has
    * either come up or failed. Runnable should check existence of
    * BluetoothService via Get() function to see if service started correctly.
    *
    * @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
    * otherwise
    */
-  nsresult Start(BluetoothReplyRunnable* aResultRunnable);
+  nsresult Start(nsIRunnable* aResultRunnable);
 
   /** 
    * Stop bluetooth services. Starts up any threads and connections that
    * bluetooth needs to operate on the current platform. Assumed to be run on
    * the main thread with delayed return for blocking startup functions via
    * runnable.
    *
    * @param aResultRunnable Runnable object to execute after bluetooth has
    * either shut down or failed. Runnable should check lack of existence of
    * BluetoothService via Get() function to see if service stopped correctly.
    *
    * @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
    * otherwise
    */
-  nsresult Stop(BluetoothReplyRunnable* aResultRunnable);
+  nsresult Stop(nsIRunnable* aResultRunnable);
 
   /** 
    * Returns the BluetoothService singleton. Only to be called from main thread.
    *
    * @param aService Pointer to return singleton into. 
    *
    * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise (if service
    * has not yet been started, for instance)
@@ -244,18 +245,17 @@ protected:
   {
     mBluetoothSignalObserverTable.Init();
   }
 
   virtual ~BluetoothService()
   {
   }
 
-  nsresult StartStopBluetooth(BluetoothReplyRunnable* aResultRunnable,
-                              bool aStart);
+  nsresult StartStopBluetooth(nsIRunnable* aResultRunnable, bool aStart);
   // This function is implemented in platform-specific BluetoothServiceFactory
   // files
   static BluetoothService* Create();
 
   typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
   typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
   BluetoothSignalObserverTable;
 
--- a/dom/bluetooth/nsIDOMBluetoothDevice.idl
+++ b/dom/bluetooth/nsIDOMBluetoothDevice.idl
@@ -1,21 +1,22 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
-[scriptable, builtinclass, uuid(647bb64c-8d45-4642-b86b-b3b80d4c8c25)]
+[scriptable, builtinclass, uuid(4a271533-6a09-4a65-ae2b-086794c7852c)]
 interface nsIDOMBluetoothDevice : nsIDOMEventTarget
 {
   readonly attribute DOMString address;
   readonly attribute DOMString name;
+  readonly attribute DOMString icon;
   [binaryname(DeviceClass)] readonly attribute unsigned long class;
   [implicit_jscontext] readonly attribute jsval uuids;
   readonly attribute bool connected;
   readonly attribute bool paired;
   attribute nsIDOMEventListener onpropertychanged;
   attribute nsIDOMEventListener onconnected;
   attribute nsIDOMEventListener ondisconnected;
 };
--- a/dom/bluetooth/nsIDOMBluetoothManager.idl
+++ b/dom/bluetooth/nsIDOMBluetoothManager.idl
@@ -4,16 +4,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMDOMRequest;
 interface nsIDOMBluetoothAdapter;
 
-[scriptable, builtinclass, uuid(1442c310-8233-4670-8aa9-752ad673bae0)]
+[scriptable, builtinclass, uuid(033d9774-f983-422f-ab6b-06a0b540d6f2)]
 interface nsIDOMBluetoothManager : nsIDOMEventTarget
 {
   readonly attribute bool enabled;
 
   nsIDOMDOMRequest getDefaultAdapter();
-  nsIDOMDOMRequest setEnabled(in boolean enabled);
+
+  attribute nsIDOMEventListener onenabled;
+  attribute nsIDOMEventListener ondisabled;
 };
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -165,19 +165,19 @@ const CONTACT_CID        = Components.ID
 const nsIDOMContact      = Components.interfaces.nsIDOMContact;
 
 function Contact() {
   if (DEBUG) debug("Contact constr: ");
 };
 
 Contact.prototype = {
   __exposedProps__: {
-                      id: 'rw',
-                      updated: 'rw',
-                      published:  'rw',
+                      id: 'r',
+                      updated: 'r',
+                      published:  'r',
                       name: 'rw',
                       honorificPrefix: 'rw',
                       givenName: 'rw',
                       additionalName: 'rw',
                       familyName: 'rw',
                       honorificSuffix: 'rw',
                       nickname: 'rw',
                       email: 'rw',
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -259,19 +259,35 @@ DeviceStorageFile::Write(InfallibleTArra
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 nsresult
 DeviceStorageFile::Remove()
 {
-  mFile->Remove(true);
+  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+
+  bool check;
+  nsresult rv = mFile->Exists(&check);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  
+  if (!check) {
+    return NS_OK;
+  }
+
+  rv = mFile->Remove(true);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
   nsCOMPtr<IOEventComplete> iocomplete = new IOEventComplete(mFile, "deleted");
-  NS_DispatchToMainThread(iocomplete);    
+  NS_DispatchToMainThread(iocomplete);
   return NS_OK;
 }
 
 void
 DeviceStorageFile::CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
                                 uint64_t aSince)
 {
   nsString rootPath;
@@ -295,17 +311,17 @@ DeviceStorageFile::collectFilesInternal(
     return;
   }
 
   nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
   nsCOMPtr<nsIFile> f;
 
   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(f))) && f) {
 
-    int64_t msecs;
+    PRTime msecs;
     f->GetLastModifiedTime(&msecs);
 
     if (msecs < aSince) {
       continue;
      }
 
     bool isDir;
     f->IsDirectory(&isDir);
@@ -1091,17 +1107,16 @@ public:
   ~DeleteFileEvent() {}
 
   NS_IMETHOD Run()
   {
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
     mFile->Remove();
 
     nsRefPtr<nsRunnable> r;
-
     bool check = false;
     mFile->mFile->Exists(&check);
     if (check) {
       r = new PostErrorEvent(mRequest, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST, mFile);
     }
     else {
       r = new PostResultEvent(mRequest, mFile->mPath);
     }
--- a/dom/dom-config.mk
+++ b/dom/dom-config.mk
@@ -33,16 +33,17 @@ DOM_SRCDIRS = \
   dom/camera \
   $(NULL)
 
 ifdef MOZ_B2G_RIL
 DOM_SRCDIRS += \
   dom/system/gonk \
   dom/telephony \
   dom/wifi \
+  dom/icc/src \
   $(NULL)
 endif
 
 ifdef MOZ_B2G_BT
 DOM_SRCDIRS += dom/bluetooth
 endif
 
 LOCAL_INCLUDES += $(DOM_SRCDIRS:%=-I$(topsrcdir)/%)
new file mode 100644
--- /dev/null
+++ b/dom/icc/Makefile.in
@@ -0,0 +1,14 @@
+# 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/.
+
+DEPTH            = @DEPTH@
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+PARALLEL_DIRS = interfaces src
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/Makefile.in
@@ -0,0 +1,21 @@
+# 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/.
+
+DEPTH            = ../../..
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+XPIDL_MODULE = dom_icc
+
+include $(topsrcdir)/dom/dom-config.mk
+
+XPIDLSRCS = \
+  nsIDOMIccManager.idl \
+  SimToolKit.idl \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/SimToolKit.idl
@@ -0,0 +1,356 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEvent.idl"
+
+interface nsIDOMEvent;
+
+dictionary MozStkTextMessage
+{
+  /**
+   * Text String.
+   *
+   * @see TS 11.14, clause 12.15, Text String.
+   */
+  DOMString text;
+
+  /**
+   * Indicate this text message is high priority or normal priority.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 1.
+   *
+   * High priority text shall be displayed on the screen immediately, except if
+   * there is a conflict of priority level of alerting such as incoming calls
+   * or a low battery warning. In that situation, the resolution is left to
+   * the terminal. If the command is rejected in spite of the high priority,
+   * the terminal shall inform the ICC with resultCode is
+   * TERMINAL_CRNTLY_UNABLE_TO_PROCESS in MozStkResponse.
+   *
+   * true: high priority
+   * false: normal priority
+   */
+  boolean isHighPriority;
+
+  /**
+   * Need to wait for user to clear message or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 8.
+   *
+   * If this attribute is true, but user doesn't give any input within a period
+   * of time(said 30 secs), the terminal shall inform the ICC with resultCode
+   * is NO_RESPONSE_FROM_USER in MozStkResponse.
+   *
+   * true: Wait for user to clear message.
+   * false: clear message after a delay.
+   */
+  boolean userClear;
+
+  /**
+   * Need to response immediately or not.
+   *
+   * @see TS 11.14, clause 12.43, Immediate response.
+   *
+   * When this attribute is true, the terminal shall immediately send
+   * MozStkResponse with resultCode is OK.
+   *
+   * true: The terminal shall send response immediately.
+   * false: otherwise.
+   */
+  boolean responseNeeded;
+};
+
+dictionary MozStkItem
+{
+  /**
+   * Identifier of item.
+   *
+   * The identifier is a single byte between '01' and 'FF'. Each item shall
+   * have a unique identifier within an Item list.
+   */
+  unsigned short identifier;
+
+  /**
+   * Text string of item.
+   */
+  DOMString text;
+};
+
+dictionary MozStkMenu
+{
+  /**
+   * Array of MozStkItem.
+   *
+   * @see TS 11.14, clause 12.9
+   */
+  jsval items; // MozStkItem[]
+
+  /**
+   * Presentation type, one of TYPE_*.
+   */
+  unsigned short presentationType;
+
+  /**
+   * Title of the menu.
+   */
+  DOMString title;
+
+  /**
+   * Default item identifier of the menu.
+   */
+  unsigned short defaultItem;
+
+  /**
+   * Help information available or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, SET UP MENU, bit 8.
+   *
+   * true: help information available.
+   * false: no help information available.
+   */
+  boolean isHelpAvailable;
+};
+
+dictionary MozStkInput
+{
+  /**
+   * Text for the ME to display in conjunction with asking the user to respond.
+   */
+  DOMString text;
+
+  /**
+   * Minimum length of response.
+   */
+  unsigned short minLength;
+
+  /**
+   * Maximum length of response.
+   */
+  unsigned short maxLength;
+
+  /**
+   * Text for the ME to display, corresponds to a default text string offered
+   * by the ICC.
+   */
+  DOMString defaultText;
+
+  /**
+   * Input format.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 1.
+   *
+   * true: Alphabet set.
+   * false: Digits only.
+   */
+  boolean isAlphabet;
+
+  /**
+   * Alphabet encoding.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 2.
+   *
+   * true: UCS2 alphabet.
+   * false: default SMS alphabet.
+   */
+  boolean isUCS2;
+
+  /**
+   * Visibility of input.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 3.
+   *
+   * true: User input shall not be revealed in any way.
+   * false: ME may echo user input on the display.
+   */
+  boolean hideInput;
+
+  /**
+   * Yes/No response is requested.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INKEY, bit 3.
+   *
+   * true: Yes/No response is requested, and character sets
+   *       (Alphabet set and UCS2) are disabled.
+   * false: Character sets (Alphabet set and UCS2) are enabled.
+   */
+  boolean isYesNoRequested;
+
+  /**
+   * User input in packed or unpacked format.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 4.
+   *
+   * true: User input to be in SMS packed format.
+   * false: User input to be in unpacked format.
+   */
+  boolean isPacked;
+
+  /**
+   * Help information available or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 8.
+   *
+   * true: help information available.
+   * false: no help information available.
+   */
+  boolean isHelpAvailable;
+};
+
+dictionary MozStkBrowserSetting
+{
+  /**
+   * Confirm message to launch browser.
+   *
+   * @see MozStkTextMessage for the detail specification of
+   *      confirmMessage.
+   */
+  jsval confirmMessage;
+
+  /**
+   * The URL to be opened by browser.
+   */
+  DOMString url;
+
+  /**
+   * One of STK_BROWSER_MODE_*.
+   *
+   * @see nsIDOMMozIccManager.STK_BROWSER_MODE_*
+   */
+  unsigned short mode;
+};
+
+dictionary MozStkSetUpCall
+{
+  /**
+   * The Dialling number.
+   */
+  DOMString address;
+
+  /**
+   * The text message used in user confirmation phase.
+   *
+   * @see MozStkTextMessage for the detail specification of
+   *      confirmMessage.
+   */
+  jsval confirmMessage;
+
+  /**
+   * The text message used in call set up phase.
+   *
+   * @see MozStkTextMessage for the detail specification of
+   *      callMessage.
+   */
+  jsval callMessage;
+};
+
+dictionary MozStkCommand
+{
+  /**
+   * The number of command issued by ICC. And it is assigned
+   * by ICC may take any hexadecimal value betweean '01' and 'FE'.
+   *
+   * @see TS 11.14, clause 6.5.1
+   */
+  unsigned short commandNumber;
+
+  /**
+   * One of STK_CMD_*
+   */
+  unsigned short typeOfCommand;
+
+  /**
+   * Qualifiers specific to the command.
+   */
+  unsigned short commandQualifier;
+
+  /**
+   * options varies accrording to the typeOfCommand in MozStkCommand.
+   *
+   * When typeOfCommand is
+   * - STK_DISPLAY_TEXT
+   * - STK_SET_UP_IDLE_MODE_TEXT
+   * - STK_REFRESH
+   * - STK_SEND_{SS|USSD|SMS|DTMF},
+   * options is MozStkTextMessage.
+   *
+   * When typeOfCommand is
+   * - STK_SELECT_ITEM
+   * - STK_SET_UP_MENU
+   * options is MozStkMenu.
+   *
+   * When typeOfCommand is
+   * - STK_GET_INKEY
+   * - STK_GET_INPUT,
+   * options is MozStkInput.
+   *
+   * When typeOfCommand is
+   * - STK_LAUNCH_BROWSER
+   * options is MozStkBrowserSetting.
+   *
+   * When typeOfCommand is
+   * - STK_SET_UP_CALL
+   * options is MozStkSetUpCall.
+   */
+  jsval options;
+};
+
+[scriptable, builtinclass, uuid(06bbc6fa-9b59-4db6-b66b-3b26f9c379df)]
+interface nsIDOMMozStkCommandEvent : nsIDOMEvent
+{
+  /**
+   * See nsIDOMMozStkCommand for the detail of command.
+   */
+  [implicit_jscontext]
+  readonly attribute jsval command;
+};
+
+dictionary MozStkResponse
+{
+  /**
+   * One of RESULT_*
+   */
+  unsigned short resultCode;
+
+  /**
+   * The identifier of the item selected by user.
+   *
+   * @see MozStkItem.identifier
+   */
+  unsigned short itemIdentifier;
+
+  /**
+   * User input.
+   */
+  DOMString input;
+
+  /**
+   * Alphabet encoding.
+   *
+   * @see MozStkInput.isUCS2
+   */
+  boolean isUCS2;
+
+  /**
+   * YES/NO response.
+   *
+   * @see MozStkInput.isYesNoRequested
+   */
+  boolean isYesNo;
+
+  /**
+   * Packed or unpacked format.
+   *
+   * @see MozStkInput.isPacked
+   */
+  boolean isPacked;
+
+  /**
+   * User has confirmed or rejected the call during STK_CMD_CALL_SET_UP.
+   *
+   * @see RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
+   *
+   * true: Confirmed by User.
+   * false: Rejected by User.
+   */
+  boolean hasConfirmed;
+};
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/nsIDOMIccManager.idl
@@ -0,0 +1,177 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEventTarget.idl"
+#include "SimToolKit.idl"
+
+interface nsIDOMEventListener;
+
+[scriptable, builtinclass, uuid(6ca8ac2b-0c7b-40bf-8eb3-dbd16f89d82f)]
+interface nsIDOMMozIccManager : nsIDOMEventTarget
+{
+  /**
+   * STK Menu Presentation types.
+   */
+  const unsigned short STK_MENU_TYPE_NOT_SPECIFIED      = 0x00;
+  const unsigned short STK_MENU_TYPE_DATA_VALUES        = 0x01;
+  const unsigned short STK_MENU_TYPE_NAVIGATION_OPTIONS = 0x03;
+
+  /**
+   * Browser launch mode.
+   */
+  const unsigned short STK_BROWSER_MODE_LAUNCH_IF_NOT_ALREADY_LAUNCHED = 0x00;
+  const unsigned short STK_BROWSER_MODE_USING_EXISTING_BROWSER         = 0x02;
+  const unsigned short STK_BROWSER_MODE_USING_NEW_BROWSER              = 0x03;
+
+  /**
+   * STK Proactive commands.
+   *
+   * @see TS 11.14, clause 13.4
+   */
+  const unsigned short STK_CMD_REFRESH               = 0x01;
+  const unsigned short STK_CMD_SET_UP_CALL           = 0x10;
+  const unsigned short STK_CMD_SEND_SS               = 0x11;
+  const unsigned short STK_CMD_SEND_USSD             = 0x12;
+  const unsigned short STK_CMD_SEND_SMS              = 0x13;
+  const unsigned short STK_CMD_SEND_DTMF             = 0x14;
+  const unsigned short STK_CMD_LAUNCH_BROWSER        = 0x15;
+  const unsigned short STK_CMD_DISPLAY_TEXT          = 0x21;
+  const unsigned short STK_CMD_GET_INKEY             = 0x22;
+  const unsigned short STK_CMD_GET_INPUT             = 0x23;
+  const unsigned short STK_CMD_SELECT_ITEM           = 0x24;
+  const unsigned short STK_CMD_SET_UP_MENU           = 0x25;
+  const unsigned short STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
+
+  /**
+   * STK Result code.
+   *
+   * @see TS 11.14, clause 12.12
+   *
+   * Results '0X' and '1X' indicate that the command has been performed.
+   */
+  /** Command performed successfully */
+  const unsigned short STK_RESULT_OK                                = 0x00;
+
+  /** Command performed with partial comprehension */
+  const unsigned short STK_RESULT_PRFRMD_WITH_PARTIAL_COMPREHENSION = 0x01;
+
+  /** Command performed, with missing information */
+  const unsigned short STK_RESULT_PRFRMD_WITH_MISSING_INFO          = 0x02;
+
+  /** REFRESH performed with additional EFs read */
+  const unsigned short STK_RESULT_PRFRMD_WITH_ADDITIONAL_EFS_READ   = 0x03;
+
+  /** Command performed successfully, limited service */
+  const unsigned short STK_RESULT_PRFRMD_LIMITED_SERVICE            = 0x06;
+
+  /** Proactive UICC session terminated by the user */
+  const unsigned short STK_RESULT_UICC_SESSION_TERM_BY_USER         = 0x10;
+
+  /** Backward move in the proactive UICC session requested by the user */
+  const unsigned short STK_RESULT_BACKWARD_MOVE_BY_USER             = 0x11;
+
+  /** No response from user */
+  const unsigned short STK_RESULT_NO_RESPONSE_FROM_USER             = 0x12;
+
+  /** Help information required by the user */
+  const unsigned short STK_RESULT_HELP_INFO_REQUIRED                = 0x13;
+
+  /** USSD or SS transaction terminated by the user */
+  const unsigned short STK_RESULT_USSD_SS_SESSION_TERM_BY_USER      = 0x14;
+
+  /**
+   * Results '2X' indicate to the UICC that it may be worth re-trying the
+   * command at a later opportunity.
+   */
+  /** Terminal currently unable to process command */
+  const unsigned short STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS = 0x20;
+
+  /** Network currently unable to process command */
+  const unsigned short STK_RESULT_NETWORK_CRNTLY_UNABLE_TO_PROCESS  = 0x21;
+
+  /** User did not accept the proactive command */
+  const unsigned short STK_RESULT_USER_NOT_ACCEPT                   = 0x22;
+
+  /** User cleared down call before connection or network release */
+  const unsigned short STK_RESULT_USER_CLEAR_DOWN_CALL              = 0x23;
+
+  /** Launch browser generic error code */
+  const unsigned short STK_RESULT_LAUNCH_BROWSER_ERROR              = 0x26;
+
+  /**
+   * Results '3X' indicate that it is not worth the UICC re-trying with an
+   * identical command, as it will only get the same response. However, the
+   * decision to retry lies with the application.
+   */
+  /** Command beyond terminal's capabilities */
+  const unsigned short STK_RESULT_BEYOND_TERMINAL_CAPABILITY        = 0x30;
+
+  /** Command type not understood by terminal */
+  const unsigned short STK_RESULT_CMD_TYPE_NOT_UNDERSTOOD           = 0x31;
+
+  /** Command data not understood by terminal */
+  const unsigned short STK_RESULT_CMD_DATA_NOT_UNDERSTOOD           = 0x32;
+
+  /** Command number not known by terminal */
+  const unsigned short STK_RESULT_CMD_NUM_NOT_KNOWN                 = 0x33;
+
+  /** SS Return Error */
+  const unsigned short STK_RESULT_SS_RETURN_ERROR                   = 0x34;
+
+  /** SMS RP-ERROR */
+  const unsigned short STK_RESULT_SMS_RP_ERROR                      = 0x35;
+
+  /** Error, required values are missing */
+  const unsigned short STK_RESULT_REQUIRED_VALUES_MISSING           = 0x36;
+
+  /** USSD Return Error */
+  const unsigned short STK_RESULT_USSD_RETURN_ERROR                 = 0x37;
+
+  /** MultipleCard commands error */
+  const unsigned short STK_RESULT_MULTI_CARDS_CMD_ERROR             = 0x38;
+
+  /**
+   * Interaction with call control by USIM or MO short message control by
+   * USIM, permanent problem
+   */
+  const unsigned short STK_RESULT_USIM_CALL_CONTROL_PERMANENT       = 0x39;
+
+  /** Bearer Independent Protocol error */
+  const unsigned short STK_RESULT_BIP_ERROR                         = 0x3a;
+
+  /**
+   * Send the response back to ICC after an attempt to execute STK Proactive
+   * Command.
+   *
+   * @param command
+   *        Command received from ICC. See MozStkCommand.
+   * @param response
+   *        The response that will be sent to ICC.
+   * @see MozStkResponse for the detail of response.
+   */
+  void sendStkResponse(in jsval command, in jsval response);
+
+  /**
+   * Send the "Menu Selection" Envelope command to ICC for menu selection.
+   *
+   * @param itemIdentifier
+   *        The identifier of the item selected by user.
+   * @param helpRequested
+   *        true if user requests to provide help information, false otherwise.
+   */
+  void sendStkMenuSelection(in unsigned short itemIdentifier,
+                            in boolean        helpRequested);
+
+  /**
+   * The 'stkcommand' event is notified whenever STK Proactive Command is
+   * issued from ICC.
+   */
+  attribute nsIDOMEventListener onstkcommand;
+
+  /**
+   * 'stksessionend' event is notified whenever STK Session is terminated by
+   * ICC.
+   */
+  attribute nsIDOMEventListener onstksessionend;
+};
new file mode 100644
--- /dev/null
+++ b/dom/icc/src/IccManager.cpp
@@ -0,0 +1,167 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Services.h"
+#include "nsIDOMClassInfo.h"
+#include "nsIObserverService.h"
+#include "IccManager.h"
+#include "SimToolKit.h"
+#include "StkCommandEvent.h"
+
+#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
+
+#define STKCOMMAND_EVENTNAME      NS_LITERAL_STRING("stkcommand")
+#define STKSESSIONEND_EVENTNAME   NS_LITERAL_STRING("stksessionend")
+
+DOMCI_DATA(MozIccManager, mozilla::dom::icc::IccManager)
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+const char* kStkCommandTopic     = "icc-manager-stk-command";
+const char* kStkSessionEndTopic  = "icc-manager-stk-session-end";
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(IccManager)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IccManager,
+                                                  nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(stkcommand)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(stksessionend)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IccManager,
+                                                nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(stkcommand)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(stksessionend)
+  tmp->mProvider = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IccManager)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMozIccManager)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozIccManager)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozIccManager)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(IccManager, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(IccManager, nsDOMEventTargetHelper)
+
+IccManager::IccManager()
+{
+  mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+
+  // Not being able to acquire the provider isn't fatal since we check
+  // for it explicitly below.
+  if (!mProvider) {
+    NS_WARNING("Could not acquire nsIMobileConnectionProvider!");
+  }
+}
+
+void
+IccManager::Init(nsPIDOMWindow* aWindow)
+{
+  BindToOwner(aWindow);
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (!obs) {
+    NS_WARNING("Could not acquire nsIObserverService!");
+    return;
+  }
+
+  obs->AddObserver(this, kStkCommandTopic, false);
+  obs->AddObserver(this, kStkSessionEndTopic, false);
+}
+
+void
+IccManager::Shutdown()
+{
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (!obs) {
+    NS_WARNING("Could not acquire nsIObserverService!");
+    return;
+  }
+
+  obs->RemoveObserver(this, kStkCommandTopic);
+  obs->RemoveObserver(this, kStkSessionEndTopic);
+}
+
+// nsIObserver
+
+NS_IMETHODIMP
+IccManager::Observe(nsISupports* aSubject,
+                    const char* aTopic,
+                    const PRUnichar* aData)
+{
+  if (!strcmp(aTopic, kStkCommandTopic)) {
+    nsString stkMsg;
+    stkMsg.Assign(aData);
+    nsRefPtr<StkCommandEvent> event = StkCommandEvent::Create(stkMsg);
+
+    NS_ASSERTION(event, "This should never fail!");
+
+    nsresult rv = event->Dispatch(ToIDOMEventTarget(), STKCOMMAND_EVENTNAME);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic, kStkSessionEndTopic)) {
+    InternalDispatchEvent(STKSESSIONEND_EVENTNAME);
+    return NS_OK;
+  }
+
+  MOZ_NOT_REACHED("Unknown observer topic!");
+
+  return NS_OK;
+}
+
+// nsIDOMMozIccManager
+
+NS_IMETHODIMP
+IccManager::SendStkResponse(const JS::Value& aCommand,
+                            const JS::Value& aResponse)
+{
+  if (!mProvider) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mProvider->SendStkResponse(GetOwner(), aCommand, aResponse);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccManager::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested)
+{
+  if (!mProvider) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mProvider->SendStkMenuSelection(GetOwner(), aItemIdentifier, aHelpRequested);
+  return NS_OK;
+}
+
+nsresult
+IccManager::InternalDispatchEvent(const nsAString& aType)
+{
+  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nullptr, nullptr);
+  nsresult rv = event->InitEvent(aType, false, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = event->SetTrusted(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool dummy;
+  rv = DispatchEvent(event, &dummy);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+
+NS_IMPL_EVENT_HANDLER(IccManager, stkcommand)
+NS_IMPL_EVENT_HANDLER(IccManager, stksessionend)
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/icc/src/IccManager.h
@@ -0,0 +1,57 @@
+/* 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/. */
+
+#ifndef mozilla_dom_icc_IccManager_h
+#define mozilla_dom_icc_IccManager_h
+
+#include "nsCycleCollectionParticipant.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsIDOMIccManager.h"
+#include "nsIMobileConnectionProvider.h"
+#include "nsIObserver.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+class IccManager : public nsDOMEventTargetHelper
+                 , public nsIDOMMozIccManager
+                 , public nsIObserver
+{